Our latest custom Test::More looks something like this:
package Our::Test::More; use strict; use warnings; use Hook::LexWrap; # XXX don't use 'base' as it can override our signal handlers use Test::Builder::Module; our ( @ISA, @EXPORT ); use Test::More; use Test::Differences; use Test::Exception; BEGIN { @ISA = qw(Test::Builder::Module); @EXPORT = ( @Test::More::EXPORT, @Test::Differences::EXPORT, @Test::Exception::EXPORT, 'explain', ); if ( Test::Differences->VERSION <= 0.47 ) { # XXX There's a bug in Test::Differences 0.47 which attempts to render # an AoH in a cleaner 'table' format. # http://rt.cpan.org/Public/Bug/Display.html?id=29732 no warnings 'redefine'; *Test::Differences::_isnt_HASH_of_scalars = sub { return 1 if ref ne "HASH"; return scalar grep ref, values %$_; }; } } sub import { for my $i (0 .. $#_) { if ('fail' eq $_[$i]) { splice @_, $i, 1; wrap 'Test::Builder::ok', post => sub { if (![ $_[0]->summary ]->[-1]) { die "Test failed. Halting"; } }; last; } } # 'magic' goto to avoid updating the callstack goto &Test::Builder::Module::import; } sub explain { return unless $ENV{TEST_VERBOSE}; Test::More::diag(@_); } 1;
This does several things:
The three test modules included are ones that we use constantly, so it makes sense to include them.
The explain() function was needed because several developers really want diag() output for times when you want to read the test narrative more clearly. However, that output is useless when running the full test suite in non-verbose mode. It requires the latest version of Test::Harness in subversion because the $ENV{TEST_VERBOSE} functionality was accidentally left out (that would be my fault, I think).
The 'fail' argument to the import list is very handy when you have several hundred tests scrolling by and you hate scrolling back up through reams of junk to find the failure. Use it like this:
use Our::Test::More 'fail', 'no_plan'; BEGIN { use_ok 'Some::Module', ':all' or die; } ok defined &foobar, 'foobar() is in the house!'; throws_ok { foobar( 5 ) } 'My::Exception', "... but he don't like no arguments"; eq_or_diff foobar(), foobar(), "... and he repeats himself a lot"' ok defined &barfoo, 'barfoo() has somehow shown up'; foreach my $thing (barfoo()) { explain("Testing $thing"); do_some_test($thing); } ...
As you can see, you get more testing functions, the "explain()" stuff might spew out loads of junk, but you won't see it when you run the full test suite, and it will halt as soon as the first test fails.
Re:explain() should be in Test::More core
Ovid on 2008-01-11T18:01:42
It's getting to the point where I'm thinking about just releasing a custom Test::More::Extra (or something) to handle this stuff. The problem is figuring out which test modules are the most common. Just choosing mine seems a bit cheeky.
$ perl -wle 'use OurMore "no_plan"; is 23, 42'
not ok 1
# Failed test at -e line 1.
# got: '23'
# expected: '42'
1..1
# Looks like you failed 1 test of 1.
$ perl -wle 'use OurMore "fail", "no_plan"; is 23, 42'
not ok 1
# Failed test at/usr/local/perl/5.8.8/lib/Test/More.pm line 329.
Test failed. Halting at OurMore.pm line 44.
1..1
Re:Dude, where's my diagnostics?
Ovid on 2008-01-12T09:35:19
Thanks. I'll look into this more closely.
Re:Test::Differences vs Test::Deep
Ovid on 2008-01-12T09:52:44
I just added Test::Deep. Consider the code:
use Our::Test::More 'no_plan';
my ( $foo, $bar ) = ( [qw/1 2 3 4 5/], [qw/1 2 trois 4 cinq/] );
eq_or_diff $foo, $bar;
cmp_deeply $foo, $bar;Consider the output:
# Failed test at test.t line 10.
# +----+-----+----------+
# | Elt|Got |Expected |
# +----+-----+----------+
# | 0|1 |1 |
# | 1|2 |2 |
# * 2|3 |trois *
# | 3|4 |4 |
# * 4|5 |cinq *
# +----+-----+----------+
not ok 2
# Failed test at test.t line 11.
# Compared $data->[2]
# got : '3'
# expect : 'trois'With Test::Differences, I can see and potentially fix all of the problems at once. I've used Test::Deep for the bag tests, but that's about it.
Also, last night I decided to figure out which Test modules were the most popular. Out of almost 300 I found used in CPAN modules, here are the top ten:
Test::More 44473
Test::Exception 1380
Test::Simple 731
Test::Base 316
Test::Builder::Tester 193
Test::NoWarnings 174
Test::Differences 150
Test::MockObject 139
Test::Deep 127
Test::Warn 118Test::Deep certainly warrants more attention here.