What is unit testing? Unit testing is a method for verifying that you software does what it is supposed to. The idea is that you have a testing framework (Test::Harness in our case) that will automatically run your tests for you, reporting any failures. You'll then write a series of tests to exercise every function of every module in your program. [See What needs to be tested? for more information.] Instead of boring you with details, let's start with an example.
How do I do it? I'll start with the Koha.pm module. It contains four functions; slashifyDate, fixEthnicity, borrowercategories, and ethnicitycategories. All of our tests should go into the t/ directory, and should be put into a file showing which module we're testing. In this case, we'll create a file t/koha.t to hold our tests. Tests start with a bit of magic to make them work:
BEGIN { $| = 1; print "1..1\n"; } END {print "not ok 1\n" unless $loaded;} use C4::Koha; $loaded = 1; print "ok 1\n";
This sets up the test, tells the harness that it will be running one test (the 'print ā1..1\nā' bit), and ensures that the test can load the module (that would be the first test).
If we run the test now, we'll get:
[pate@gnupate t]$ perl koha.t 1..1 ok 1 [pate@gnupate t]$
or:
[pate@gnupate koha]$ ./testKoha.pl t/koha..............ok All tests successful. Files=1, Tests=1, 1 wallclock secs ( 0.25 cusr + 0.11 csys = 0.36 CPU) [pate@gnupate koha]$
slashifyDate takes a string representing a (MySQL style) date, replaces '-'s with '/'s and returns it in European style date. We can test it like this:
$date = "02/01/2002"; $newdate = &slashifyDate("2002-01-02");
if ($date eq $newdate) { print "ok 2\n"; } else { print "not ok 2\n"; }
We'll also need to let the harness know that we've added a test, so let's change the first line to look like this:
BEGIN { $| = 1; print "1..2\n"; }
Now, running the tests looks like this:
[pate@gnupate koha]$ ./testKoha.pl t/koha..............ok All tests successful. Files=1, Tests=2, 1 wallclock secs ( 0.23 cusr + 0.09 csys = 0.32 CPU) [pate@gnupate koha]$
Then, we can go on and add tests until we end up with something like:
[pate@gnupate koha]$ ./testKoha.pl t/format............ok t/koha..............ok t/output............ok t/require...........ok All tests successful. Files=4, Tests=40, 1 wallclock secs ( 1.25 cusr + 0.11 csys = 1.36 CPU)
What needs to be tested? You don't need to test everything, just the things that can fail.
Ok, so maybe this is overkill. But we really should test aggresively. Not only should we right tests for expected input, but also for fringe cases that should produce failures.
Additionally, anytime we fix a bug, we should try to represent it in one (or more) unit tests. That way we can feel comfortable that no one accidentally reintroduces the bug later on.
Who writes the tests? We do. In fact, it is best if the programmer who sits down to write new code would do well to write some tests first. This way, he (or she) will know they got the code right. It's a tremendously liberating way to write code.
When do I run the tests? Please, run the tests every time you're ready to check code in! Then fix any errors before you check in. Right now, the tests all pass on the rel_1_2 branch. Let's keep it that way ;)