Test::Class::Filter::Tags

I'm happy to announce the release of Test::Class::Filter::Tags. This module uses the new filter support introduced in version 0.36 of Test::Class to allow selective running of Test::Class tests.

With the filter support of Test::Class, it's now possible to supply any number of filter subs, when running Test::Class tests. Each filter is given the opportunity to suppress the running of each test; If any filter says to suppress a specific test, that test will not be executed.

Using this mechanism, when Test::Class::Filter::Tags is used in your Test::Class classes, you can specify 'Tags' attributes on non-fixture (ie, not startup, setup, teardown or shutdown tests). When running tests, you can set an environment variable of TEST_TAGS, to run only the subset of the tests that have the specified tags. Conversely, you can limit a subset of tests that have specified tags via the TEST_TAGS_SKIP environment variable. Both of these vars can be used to give even more granularity in deciding what tests are run.

As an example of this, consider the following: You have a large test suite, that takes a long time to run. When doing a bit of work, you don't want to run the full test suite every time a change is made. Instead, there are some core tests that exercise your code and can run in a reasonable length of time. Only when looking to merge the new code back into the main branch do you want the full test suite run.

When using vanilla Test::Class, the only mechanism that can support the above behaviour is to separate the two classes of tests into multiple test classes, and have multiple driver scripts that load only a subset of tests; Only classes that exercise the core code for the quick subset of tests, and a full list of classes, that execute all tests, to be run at integration or deployment time.

While the above is a workable solution, it's not ideal, in that it forces arbitrary separation of test code into disparate classes, that would ideally be contained within a single class. Tests that exercise the similar functionality are now contained in multiple test classes, losing some of the benefit of using Test::Class to group tests.

Using Test::Class::Filter::Tags, you can get around the above issue. By tagging your core developer tests, you can then choose to run just those tests. Simply specify the relevant tags in the TEST_TAGS env var when running the tests, and only that subset will be tested, no matter where how many test classes they're in, or whether they're interspersed with other tests that don't have the relevant tags. For integration, just don't specify TEST_TAGS, and all tests will be run.

An example of this is as follows:

package t::Foo;

use Foo;

# Get access to the 'Tags' attribute, and install the Test::Class filter.
use Test::Class::Filter::Tags;
use Test::More;

use base 'Test::Class';

sub object_creation : Test( 1 ) Tags( fast ) {
    my $foo = Foo->new( 1 );

    ok( defined $foo, "Foo lives!" );
}

sub long_slow_test : Tests( 1 ) Tags( slow ) {
    my $foo = Foo->new( "265252859812191058636308480000001" );

    is( Foo->is_prime, 1, "Finally got a result" );
}

sub non_tagged : Tests( 1 ) {
    is( 1, 1, "*sigh*" )
}

# more tests with these, or other tags

You can now run only the fast tests, via running your test driver script as:

$ TEST_TAGS=fast test_driver.pl

This gives a result of:

1..1
ok 1 - Foo lives!

Only the tests marked fast were run; even tests with no tags were filtered out. Alternatively, you may have a number of other tags, and want to run all but the slow tests, this can again be accomplished via:

$ TEST_TAGS_SKIP=slow test_driver.pl
1..2
ok 1 - *sigh*
ok 2 - Foo lives!

If you have a large Test::Class test suite that needs organising, please take a look at this module. I welcome any feedback about how to improve this module, so please get in touch with me at makk384@gmail.com if you find this module is missing some functionality you'd desire.

About Mark Morgan

user-pic Testing, and general Perl work.