If you find having to increment the number at the top of your test script every time you add a test irritating, you can use the automatic, Do What I Mean, form:

plan tests;

In this case, Test::Assertions will read your code and count the number of ASSERT statements and use this for the expected number of tests. A caveat is that it expects all your ASSERT statements to be executed once only, hence ASSERTs in if and foreach blocks will fool Test::Assertions and you'll have to maintain the count manually in these cases. Furthermore, it uses caller() to get the filename of the code so it may not work if you invoke your program with a relative filename and then change working directory before calling this automatic "plan tests;" form.

Test::Assertions offers a couple of additional functions - only() and ignore() to control which tests will be reported. Usage is as follows:

The routines for constructing tests are deliberately ALL CAPS so you can discriminate at a glance between the test and what is being tested. To check something does what expected, use ASSERT:

ASSERT(1 == 1);

This gives the output:

ok 1

An optional 2nd arg may be supplied for a comment to label the test:

ASSERT(1 == 1, "an example test");

This gives the output:

ok 1 (an example test)

In the interest of brevity of documentation, I'll omit the 2nd argument from my examples below. For your real-world tests, labelling the output is strongly recommended so when something fails you know what it is.

If you are hopelessly addicted to invoking your tests with an ok() routine, Test::Assertions has a concession for Test::Simple/More junkies:

use Test::Assertions qw(test/ok);
plan tests => 1;
ok(1, "ok() works just like ASSERT()");

For routines that return large strings or write to files (e.g. templating), you might want to have your expected output held externally in a file. Test::Assertions provides a few routines to make this easy. EQUALS_FILE compares a string to the contents of a file:

ASSERT( EQUALS_FILE($returned, "expected.txt") );

Whereas FILES_EQUAL compares the contents of 2 files:

$object_to_test->write_file("observed.txt");
ASSERT( FILES_EQUAL("observed.txt", "expected.txt") );
unlink("observed.txt"); #always clean up so state on 2nd run is same as 1st run

If your files contain serialized data structures, e.g. the output of Data::Dumper, you may wish to use do(), or eval() their contents, and use the EQUAL() routine to compare the structures, rather than comparing the serialized forms directly.

The MATCHES_FILE routine compares a string with regex that is read from a file, which is most useful if your string contains dates, timestamps, filepaths, or other items which might change from one run of the test to the next, or across different machines:

ASSERT( MATCHES_FILE($string_to_examine, "expected.regex.txt") );

Another thing you are likely to want to test is code raising exceptions with die(). The DIED() function confirms if a coderef raises an exception:

ASSERT( DIED(
sub {
$object_to_test->method(@bad_inputs);
}
));

The DIED routine doesn't clobber $@, so you can use this in your test description:

For complex systems you may have a whole tree of unit tests, corresponding to different areas of functionality of the system. For example, there may be a set of tests corresponding to the expression evaluation sublanguage within a templating system. Rather than simply aggregating everything with Test::Harness in one flat list, you may want to aggregate each subtree of related functionality so that the Test::Harness summarisation is across these higher-level units.

Test::Assertions provides two functions to aggregate the output of other tests. These work on result strings (starting with "ok" or "not ok"). ASSESS is the lower-level routine working directly on result strings, ASSESS_FILE runs a unit test script and parses the output. In a scalar context they return a summary result string:

This output is of course a suitable input to ASSESS so complex hierarchies may be created. In an array context, they return a boolean value and a description which is suitable for feeding into ASSERT (although ASSERT's $;$ prototype means it will ignore the description) :

Importing Test::Assertions with no arguments results in ASSERT statements doing nothing, but unlike ASSERT macros in C where the preprocessor filters this out before compilation, there are 2 types of residual overhead:

When Test::Assertions is imported with no arguments, the ASSERT statement is aliased to an empty sub. There is a small overhead in executing this. In practice, unless you do an ASSERT on every other line, or in a performance-critical loop, you're unlikely to notice the overhead compared to the other work that your code is doing.

The Test::Assertions module must be compiled even when it is imported with no arguments. Test::Assertions loads its helper modules on demand and avoids using pragmas to minimise its compilation overhead. Currently Test::Assertions does not go to more extreme measures to cut its compilation overhead in the interests of maintainability and ease of installation.

Unlike Carp::Assert, Test::Assertions does not come with a "built-in" constant (DEBUG in the case of Carp::Assert). Define your own constant, attach it to your own compile-time logic (e.g. env vars) and call it whatever you like.

Here's an indication of the overhead of calling ASSERT when Test::Assertions is imported with no arguments. A comparison is included with Carp::Assert just to show that it's in the same ballpark - we are not advocating one module over the other. As outlined above, using a constant to disable assertions is recommended in performance-critical code.

If using a constant to control compilation is not to your liking, you may want to experiment with SelfLoader or AutoLoader to cut down the compilation overhead further by delaying compilation of some of the subroutines in Test::Assertions (see SelfLoader and AutoLoader for more information) until the first time they are used.