Test::More is a widely used module for Unit Tests in Perl. With Test::More your tests look like this:
# Test method_a()See how we need to come up with many versions of the
my $expected_1 = 23 * $CONSTANT; # some value we expect;
is( $expected_1, $object->method_a(23),
"method_a(23) returned expected value.");
my $expected_2 = 17 * $CONSTANT; # A new expected value
is( $expected_2, $object->method_a(17),
"method_a(17) returned expected value");
# Test another_method()
my $expected_3 = _get_favorite_color();
is( $expected_3, $object->another_method('favorite'),
"another_method('favorite') returned proper color.");
my $expected_4 = _get_recent_color();
is( $expected_4 $object->another_method('recent'),
"another_method('recent') returned proper color.");
$expected
variable?We could also just reuse it, but that can cause trouble if there are many tests and you forget to reset it.
It is better practice to use a different variable name for each test, but in many situations there are a couple dozen tests in that one file where it makes sense to use the same basic variable name for many different tests. That could lead to variable names like $expected_100. Also, there is always the risk that some temporary variables used for one test end up "polluting" a later test where the programmer didn't realize a variable was already defined earlier in the file.
The best solution is to isolate the code for each test, or small group of related tests into their own block, so that temporary variables for one test cannot interfere with another test or tests.
In Test::Unit each test is a subroutine, which can contain any number of assertions - so all the temporary variables and other setup for a particular group of tests are kept isolated from all the other tests. In addition, if you provide a subroutine called set_up() it is automatically called before running each test subroutine, and likewise, tear_down() is called after each test, this is useful for populating objects and test data structures, so that each test gets a clean set of test data to work with.
In Test::Unit the tests above might look like this:
sub test_method_a {Test::Unit provides a bunch of assertion methods:
my $self = shift;
my $expected_1 = 23 * $CONSTANT; # some value we expect;
$self->assert_equals( $expected_1, $object->method_a(23));
my $expected_2 = 17 * $CONSTANT;
$self->assert_equals( $expected_2, $object->method_a(17));
}
sub test_another_method {
my $self = shift;
my $expected_1 = _get_favorite_color();
$self->assert_equals($expected_1, $object->another_method('favorite'));
my $expected_2 = _get_recent_color();
$self->assert_equals($expected_2, $object->another_method('recent'));
}
assert_equals
/assert_not_equals
- Tries to guess what kind of comparison to make. Usually works fine. If the first argument (the 'expected') is an object it checks if the
==
operator has been overloaded and will use it if so. assert_num_equals
,assert_num_not_equals
,assert_str_equals
,assert_str_equals
- Force numeric/string comparison.
assert_matches(qr/PATTERN/, STRING, [, MESSAGE])
,assert_not_matches
- Assert that the regular expression matches.
assert_deep_equals(expected_ref, ref_to_test [, MESSAGE ])
- Used to compare complex data strucrtures, like hashes of arrays of hashes. Assert that the the data pointed to by ref_to_test matches the data structure pointed to by expected_ref
See also:
Tags: perl,unit tests,programming