Writing a Testing Library

     

By now, tests should seem less daunting. They're just programs; all of the normal good advice about design and organization applies. It makes sense to keep related code in the same place. In Perl terms, this is a module: a self-contained library of code.

Previous labs have demonstrated how to use several testing libraries. Some come with Perl's standard library. Others live on the CPAN, with new modules released frequently. If you find yourself solving the same testing problem repeatedly by twisting existing test modules in new directions, consider writing your own testing library. Test::Builder makes it possible.

How do I do that?

The following example implements one function of a very simple testing library. It adds one new function, is_between( ) , that tests whether a given value is between two other values. Save the code under a lib/ directory where you can reach it (see "Installing Test Modules," in Chapter 1) as Test/Between.pm :


Note: The use of subroutine prototypes is a convention in testing modules, but they're not like subroutine signatures in other languages. See the Prototypes section in perldoc perlsub for more information .
 package Test::Between;     use strict;     use warnings;     use base 'Exporter';     our@EXPORT = qw( is_between );     use Test::Builder;     my $Test = Test::Builder->new(  );     sub is_between ($$$;$)     {         my ($item, $lower, $upper, $desc) = @_;         return         (             $Test->ok( "$lower" le "$item" && "$item" le "$upper", $desc )              $Test->diag( "        $item is not between $lower and $upper" )         );     }     1; 

Now you can use it within your own test programs. Save the following code as test_between.t :

 #!perl     use strict;     use warnings;     use Test::More tests => 3;     use Test::Between;     is_between(    'b', 'a', 'c', 'simple alphabetical comparison' );     is_between(     2 ,  1 ,  3 , 'simple numeric comparison'      );     is_between(  "two",  1 ,  3 , 'mixed comparison'               ); 


Note: By design, Test:: Between doesn't allow its users to set the plan. Why reinvent the wheel when it's likely that users will use the module with Test:: Simple or Test:: More anyway?

Run the test with perl :

 $  perl test_between.t  1..3     ok 1 - simple alphabetical comparison     ok 2 - simple numeric comparison     not ok 3 - mixed comparison     #     Failed test (examples/wtm_01.t at line 12)     #         two is not between 1 and 3     # Looks like you failed 1 test of 3. 

What just happened ?

The test file behaves just like other tests shown so far, using Test::More to set up a test plan. It also uses Test::Between just as it would any other necessary module.

Test::Between uses the Exporter module to export the is_between( ) function. The action starts with Test::Builder . All of the testing modules shown so far use Test::Builder internally; it provides the basic ok( ) function, the test plans, the test counter, and all of the output functions.


Note: Use Test::Builder and your module will work with all of the other testing modules that also use Test::Builder .

Calling Test::Builder->new( ) returns a singleton, the same object every time , to all of the testing modules. This is how it keeps the testing environment consistent.

The is_between( ) function is simple by comparison. It has three required arguments ”the value to test, the lower bound, and the upper bound ”and one optional argument: the test description. The actual comparison happens on a single line:

 "$lower" le "$item" && "$item" le "$upper" 

This terse expression stringifies all of the arguments, then compares the lower bound to the item and the item to the upper bound. If the lower bound is less than or equal to the item and the item is less than or equal to the upper bound, the expression evaluates to true. Otherwise, it's false. Either way, the result is simple enough to pass to Test::Builder 's ok( ) method, along with the test description.

ok( ) records and reports the test appropriately, returning its truth or falsehood. That allows another idiom for printing diagnostic information. If the test has failed, the return value will be false and the function will call diag( ) on the Test::Builder object to print the values of the item and the bounds. This makes debugging much easier, of course.

What about...

Q:

Can you add other types of comparisons?

A:

Absolutely! is_between( ) has a few limitations, including treating all of its arguments as strings and allowing the item to equal its lower or upper bounds. As the third test showed, it's not smart enough to know that the number the string two represents is between one and three.

Test::Between would be more useful if it allowed numeric comparisons, permitted "between but not equal" tests, and supported custom sorting routines. These are all reasonably easy additions, though: just figure out how to make the proper comparison, feed the results to $Test- > ok( ) , report a failure diagnostic if necessary, and add the new function to @EXPORT .

Q:

How do you know that Test::Between works? Don't you have to write tests for your tests now?

A:

Yes, but fortunately it's not difficult. See "Testing a Testing Library," next .



Perl Testing. A Developer's Notebook
Perl Testing: A Developers Notebook
ISBN: 0596100922
EAN: 2147483647
Year: 2003
Pages: 107

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net