6.2. Unit Testing

Perl shines at unit testing. Although there's no empirical data to prove this, conversational evidence suggests that most Perl programs are short enough that unit testing is the same as system testing. People often report that their programs shrink by 90% when converted from C to Perl (our experience bears this out). A 1000-line C program requires more heavy-duty testing than a 100-line Perl program.

6.2.1. The One-Liner

Although not strictly in the category of unit testing, we must mention the utility of the one-liner. Several flags in Perl make it possible for you to test an idiom without even having to write a script, but instead just entering the code on the command line. The first of these is:

  • -e code: Execute code as though it were in a script. Put single quotes around code on Unix to prevent the shell being confused by metacharacters, and use double quotes on DOS.

We can combine this with the -w flag if we want to enable warnings. Let's say that we want to check on which way printf rounds 0.5:

%  perl -we 'printf "%1.1f %1.f
", $_+.5, $_+.5 for 1..4'
1.5 2
2.5 2
3.5 4
4.5 4

(No, that's not a mistake; that's the way the IEEE floating point standard says it should work.)

Note by the way that the -e flag has to be the last one before code; you can't type perl -ew

  • -p -n: Execute code for every line from the input, and either print $_ automatically when done (-p) or not (-n).

Say you want to find out the ASCII codes generated by certain keys on your keyboard; you could type

% perl -pe 's/(.)/" ".ord $1/ge'
					

and then hit a key followed by a newline to see its ASCII value.

  • -l (the letter 'ell', not the number one): Append an automatic newline to print statements. When combined with -n or -p, also automatically chomp the newline character off the input.

Let's say you want to find which users listed in a Unix /etc/passwd file have directories under /home:

% perl -nle 's/:.*//; print if -d "/home/$_"' /etc/passwd
					

This can most usefully be used as a first stage in a pipeline of commands that then go on to do other things with its results. Or you might want a Perl program as the final stage of a pipeline that periodically reports how many lines it has read:

% ... | perl -nle 'BEGIN{ $SIG{ALRM} = 
						sub{ print $.; alarm 10 }; 
						alarm 10 }'
					

In this case, nothing at all is being executed in the loop for each line of input!

The -l flag is particularly useful in one-liners or in short test programs in which you have only a handful of print statements and want to save the trouble of typing in all of them. However, don't leave it in production code; setting a global flag like this affects the behavior of all print statements and will produce unpleasant results from using modules that don't expect it (such as CGI.pm and Benchmark).

  • -Mmodule: Perform a use module before executing any code.

You can use this to impose strictness on your one-liners, and also as a quick test to see if a module you want is installed:

% perl -MTime::HiRes -e 0
					

This prints nothing if the Time::HiRes module is installed but complains if it isn't.

  • -c: This flag gives you the ability to check the syntax of a Perl program without actually running it. Because so much error checking is deferred until run-time in Perl, this is of limited use, but there are certainly times when it can save some time by serving as a quick sanity check.

Use one-liners for rapid prototyping of small code constructs.


Some Web shrines to the power of the one-liner have been erected at http://history.perl.org/oneliners/ and http://www.itknowledge.com/tpj/one-liners01.html (one-liners that previously appeared in The Perl Journal).

6.2.2. Assert Yourself

The CPAN module Carp::Assert, by Michael G. Schwern, exports the routine assert, which allows you to trigger fatal exceptions with explanations during testing and then disable them globally before putting the application into use.

6.2.3. Design by Contract

Design by Contract is an idea from the Eiffel world that says you can add to your routines tests that express conditions that should be true before and after they execute, and conditions that should be true all the time. The new Class::Contract module by Damian Conway provides this facility for object-oriented modules, although you need to use its methods for creating your objects; it would be hard to retrofit to an existing class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset