I'm fixing a large test script (> 1000 lines) that uses some utility methods (also > 1000 lines) to perform repeated tests on various initial data setups. This helps consolidate code. However, when a test fails it reports the line number of inside the utility method making it hard to trace which test failed.
Is it possible to configure Test::Most
to give a stacktrace instead of just a single line number when a test fails?
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use Test::Most tests => 3;
ok(1, 'first test');
note "The following includes a failed test, but a stack trace would be more helpful";
helper_sub_with_test(); # Line 13
ok(1, 'third test');
sub helper_sub_with_test {
ok(0, "second test"); # Line 17
}
Outputs:
$ perl scratch.pl
1..3
ok 1 - first test
# The following includes a failed test, but a stack trace would be more helpful
not ok 2 - second test
# Failed test 'second test'
# at scratch.pl line 17.
ok 3 - third test
# Looks like you failed 1 test of 3.
As you can see, it would be helpful if the failed test reported both line 17 and line 13 for when there are multiple calls to the utility method.
I don't believe that the Test::More infrastructure provides such a beastie, but do you really need a stack trace? Reporting line 13 alone should be sufficient, provided you give your tests descriptive names.
To report line 13 instead of line 17, just add the following to your sub:
local $Test::Builder::Level = $Test::Builder::Level + 1;
Longer example:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use Test::Most tests => 3;
ok(1, 'first test');
note "The following includes a failed test, but a stack trace would be more helpful";
helper_sub_with_test(); # Line 13
ok(1, 'third test');
sub helper_sub_with_test {
local $Test::Builder::Level = $Test::Builder::Level + 1;
ok(0, sprintf "second test (look at line %d)", __LINE__); # Line 18
}
The quick and dirty way to get what you want is to put a wrapper around Test::Builder::ok. This is how Test::Most operates.
Using Aspect makes this less of a hack.
use Carp qw(longmess);
use Test::Most;
use Aspect;
after {
# For some reason, the return value is not being captured by Aspect
my $last_test = ($_->self->summary)[-1];
print longmess if !$last_test;
} call "Test::Builder::ok";
sub foo { ok(0) }
foo();
pass;
done_testing;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With