Published on Perl.com http://www.perl.com/pub/a/2001/12/04/testing.html See this if you're having trouble printing code examples An Introduction to Testing By chromatic Someday, you'll be dubiously blessed with the job of maintenance programming.
You might need to add new features or to fix long-standing bugs. The code may
be your own or the apparently disturbed mutterings of a long-disappeared agent
of chaos. If you haven't yet been this fortunate, then download a Perl CGI script
circa 1996 and try to make it operate under Maintenance is rarely pretty, mixing forensics, psychology and playing-card house construction. Complicating the matter are concerns such as backward compatibility, portability and interoperability. You'll probably hate the learning experience, but don't miss the chance to learn some important lessons:
These rules have been well-established since the early days (think Grace Hopper) of software engineering. Good practices remain the same: Write good comments, document your assumptions and logic, test your code to death, test it again. Every serious software engineering methodology promotes testing. It is essential to newer approaches, like Extreme Programming. A comprehensive test suite helps to verify that the code performs as expected, helps to minimize the scope of future modifications, and frees developers to improve the structure and design of code without changing its behavior. Yes, this can actually work. CaveatsExperienced readers (especially those with strong math backgrounds) rightly note that testing cannot prove the absence of bugs. If it's theoretically impossible to write a non-trivial program with zero defects, it's impossible to write enough tests to prove that the program works completely. Programmers try to write bug-free code anyway, so why not test anything and everything possible? A tested program may have unknown bugs, but an untested program will. Of course, some things are truly untestable. This category includes the ``black boxes,'' such as other processes and machines, and system libraries. More things are testable than not, though. Perl allows good programmers to perform scary black magic, including system table and run-time manipulations. It's possible to create your own fake little world just to satisfy a testable interface. A little megalomania can be handy. Testing can be difficult. A wad of code with minimal documentation -- a design from the Perl 4 days -- and business logic that relies on prayer, global variables and animal sacrifice may push you to new heights of productivity, or teach you how to manage programmers. If you don't fix it now, then when do you fix it? Extreme Programming recommends revising untestable code to make it easier to maintain and to test. Sometimes, you must write simple tests, rework the code slightly, and iterate until it's palatable. Don't let the enormity of the task get you down. If you can write Perl code worth testing, then you can write tests. How Perl Module Testing WorksThis section assumes you're already familiar with perlmodinstall, having
installed a module manually. After the At its heart, a test either prints ``ok'' or ``not ok.'' That's it. Any test program or testing framework that prints results to standard output can use Test::Harness. If you're feeling epistemological (a good trait to cultivate for writing tests), you could ask ``What is truth?'':
Basic? Yes. Bogus? Not really. This is a variant of an actual Perl core test. If you understood that code, then you can write tests. Ignoring the first line for now, simply stick it in a file (truth.t) and run either the command line:
or the program:
This should produce a message saying that all tests succeeded. If not, then something is broken, and many people would be interested in fixing it. The first line of the test corresponds to Test::Harness' handy test-numbering feature. The harness needs to know how many tests to expect, and each individual test within a group can have its own number. This is for your benefit. If one test in a 100 mysteriously fails, then it's much easier to track down number 93 than it is to run through the debugger, comment out large swaths of the test suite or rely on intuitively placed print statements. Knowing truth is good, and so is discerning falsehood. Let's extend truth.t slightly. Note the addition of test numbers to each potential printable line. This is both a boon and a bane.
Besides the increasingly duplicate code, keeping test numbers synchronized is painful. False laziness is painful -- Test::Harness emits warnings if the number of actual tests run does not meet its expectations. Test writers may not mind, but spurious warnings will confuse end users and healthily lazy developers. As a rule, the simpler the output, the more people will believe that things succeeded. The stuffed, smiling Pikachu (hey, it was a birthday present from an attractive female Web designer) perched atop my monitor makes me think that a giant yellow smiley face would be even better than a simple ``ok'' message. ASCII artists, fire up your editors! Unfortunately, the truth test is repetitive and fragile. Adding a third test between the first two (the progression from ``truth'' to ``hidden truth'' to ``falsehood'' makes sense) means duplicating the if/else block and renumbering the previously second test. There's also room for a subtle bug:
Forgetting to update the first line is common. Two tests were expected; three
tests ran. The confused Test::Harness will report strange things, like
negative failure percentages. Baby Pikachu may cry. Smarter programmers
eventually apply good programming style, writing their own
The lowest levels of the Perl core test suite use this approach. It's simpler to write and handles numbering almost automatically. It lacks some features, though, and is little easier to debug.
by chromatic Enter Test::MoreSeveral modules exist to make testing easier and almost enjoyable. Test ships with modern Perl distributions and plays well with Test::Harness. The Perl-Unit suite reimplements the popular JUnit framework in Perl. The rather new Test::More module adds several features beyond those of Test. (I admit a particular bias toward the latter, though these and other modules are fine choices.) Test::More has its own
This handles strings and numbers equally well. Since version 0.36, it also distinguishes between
The second argument can be either a regular expression compiled with the
That's too cute/hideous for a real test, but the regex form is completely valid. Test::More Makes Debugging NicerThat's useful enough already, but there's more to Test::More. Test::More supports test numbering just as Test::Harness does, and
automatically provides the numbers. This is a big win in two cases: where the
test suite may accidentally fail (from a
When writing new tests, you may not know how many there will be. Use the
Extreme Programming recommends this game-like approach: add a test, run it,
write code to pass the test, repeat. When you've finished, update the Test::More also handles failures gracefully. Given the following file with a final, doomed test:
Test::More run on its own, not through Test::Harness, produces:
The error message provides the name of the file containing the tests, the number of the failed test, the line number containing the failed test, and expected and received data. This makes for easier debugging. Count tests to find an error just once, and you'll prefer this approach. Test::Harness also supports optional test comments attached to test messages. That is, it allows raw tests to say:
Nearly all Test::More functions support this as an optional parameter:
These names are required by nothing except social convention. Think of them as little test comments. If the test is wrong, or exposes a fixed bug that should never reoccur, then a descriptive name makes it clear what the test should be testing. Test::Harness silently eats the names, but they're present when run manually:
Manual test runs make for improved bug reports. Ignore these convenient tools at your own peril. Intermediate Test::More FeaturesIf the previous features weren't enough, Test::More supports still more! One
such is the notion of skippable tests. Occasionally, the presence or absence
of certain criteria obviate the need to test a feature. Consider the
There's a lot to digest. First, the skippable tests are contained in a
labelled block. The label must be SKIP. (Don't worry: you can have several
of these within a file.) Next, there should be a condition that governs
whether to skip the tests. This example checks the special variable
perlvar to find the current Perl version. The
Though the message says ok, Test::Harness will see skip and report the
tests as skipped, not passed. This should only be used for tests that
absolutely will not run due to platform or version differences. For tests you
just can't figure out yet, use Though everything is built on
They produce their own test names:
Other functions and features are documented in the Test::More documentation. As well, the Test::Tutorial manpage explains similar things with a different wit. Finally, do not forget good programming practices. Test functions are simply
standard subroutines. Tests are just Perl code. Use loops, variables, helper
subs,
That beats writing several individual ConclusionTesting is unfortunately often neglected, especially among free software projects. Think of it as getting plenty of sleep, eating vegetables, and working out regularly. It may cramp your style at first, but will improve things immensely if you do it consistently. (Results may vary if you're adding tests to a huge system that doesn't have them, like, say, Perl itself.) One goal of Perl is to make your life easier. Perl 5.8 will include Test::More and its hearty brethren, the Test::Simple manpage and the Test::Builder manpage. They exist to make writing tests less of a hassle, and even more pleasant. Consider them. The easier it is to write and maintain tests, the more likely people will do it. More and better tests improve software portability, maintainability, and reliability. You may currently compare testing to broccoli, brussel sprouts, and wind sprints. Try Test::More or another framework, and you may grow to see them as oranges, sweet potatoes with marshmallows, and a trip to the sauna. It really is good for you. Return to Related Articles from the O'Reilly Network .
Perl.com Compilation Copyright © 1998-2003 O'Reilly & Associates, Inc. | ||
|