Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

A simple test framework

by lima1 (Curate)
on Aug 10, 2007 at 15:49 UTC ( #631831=perlmeditation: print w/replies, xml ) Need Help??

I am currently working on a module with an really ugly testsuite (written by me of course ;) ). Refactoring a testsuite is no fun, but at least I want to remove all duplicated code. Currently, every single testfile looks like this:
#!perl -T use strict; use warnings; BEGIN { use lib 't'; use MyTestHelper; use Test::More; # check some external dependencies (programs and non # CPAN modules my ($skip,$msg) = MyTestHelper::skip_all(); plan skip_all => $msg if $skip; } our %features = ( A => 72, B => 148, C => 43, D => 34, ); my $number_tests; foreach ( keys %features ) { $number_tests += $features{$_}; } plan tests => $number_tests; use English qw( -no_match_vars ); use Scalar::Util qw/refadr/; use Data::Dumper; use MyModule; my $obj = MyModule->new(); FEATURE: foreach my $feature ( sort keys %features ) { SKIP: { if ( $obj->does_not_like($feature) { skip "Feature not available", $features{$feature}; } # FINALLY, the tests ... } }
Which is much code for boring stuff. I need this features feature because I test several back-ends (the features in the test). If a back-end is not available, we can skip all tests of this back-end. Another problem is that it only checks the absolute number of tests. So the test would pass if feature A had 73 tests and feature B 147 (which is not so far-fetched than you might think). I want a simple framework like:
package MyTestFramework; use base 'Test::SimpleFramework'; sub init { my ( $self ) = @_; $self->set_strict(1); $self->set_warnings(1); $self->export({ 'Scalar::Util' => 'refaddr', 'English' => '-no_match_vars', 'Data::Dumper' => undef, 'MyModule' => undef, }); $self->dependencies({ 'lftp binary in path' => $self->in_path('lftp'), 'non-CPAN module' => $self->in_inc('Non::Cpan'), }); } our @EXPORT = qw( delete_temporary_files ); sub delete_temporary_files { foreach my $file ( <t/tmp/*> ) { my ( $filename ) = $file =~ m{\A t/tmp/ ([\d\w\.\-]+) \z}xms; unlink "t/tmp/$filename"; } }
And now, my testfiles would look like this:
#perl -T BEGIN{ use lib 't'; }; use MyTestFramework; # skips all tests if one dependency was't found check_dependencies(); register_features({ A => 72, B => 148, C => 43, D => 34, }); my $obj = MyModule->new(); while (my $feature = next_feature) { skip_feature if $obj->does_not_like($feature->name); # the tests ... # dies if number of tests for feature is not correct } delete_temporary_files();
A little research on CPAN revealed, that the features of Test::SimpleFramework are a mixture of Test::Class, Test::Block (dying if number of tests of a feature is not correct) and ToolSet, although my unexperienced eyes don't see a simple solution how these three modules could be combined. I am not sure whether the world needs yet another Test::* module, but how would you refactor my old code to get a similar functionality? If it is avoidable to introduce dependencies just for the testsuite, it would be a big plus.

Or would you like to see something like this on CPAN?

UPDATE: in my tests, "features" is "backends". "features" is probably the wrong generalization. What I actually do is to test different implementations of an interface API.

Replies are listed 'Best First'.
Re: A simple test framework
by adrianh (Chancellor) on Aug 14, 2007 at 12:28 UTC

    Without seeing "the tests" its kinda hard to know what the most appropriate abstraction is. If the tests are broken up in a hierarchical manner or alongside class boundaries something like Test::Class would probably work well for you.

    If not maybe something like Test::Group or Test::Object would help?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://631831]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2017-07-26 10:00 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (388 votes). Check out past polls.