I never really understood the point of <code>prove</code>; I write my tests as normal Perl programs, launchable from the command line. <code>perl t/testname.t</code> did most of what I wanted to do.
With more than 24 tests in a file, though, I often promised myself to write or find someday a variant test harness that ignored successes and reported only failures or an all clear message.
I looked at the code of <code>prove</code> today to find where to add it, but again, it doesn't seem to do anything I really need and there was no way to add it. I moved on to Test::Harness::Straps. I don't know if anyone's ever actually used this module (and it's admittedly a bit of a mess inside, though the long-promised Test::Builder refactoring may make it easier to write), but it took 67 lines of code to do what I needed (and a little more) in a well-factored way.
I call it qtest:
#!/usr/bin/perl
use strict;
use warnings;
use Test::Harness::Straps;
my $strap = Test::Harness::Straps->new();
for my $file (@ARGV)
{
next unless -f $file;
my %results = $strap->analyze_file( $file );
if ($results{passing})
{
report( sprintf('All (%d) tests passed in %s', $results{seen}, $file));
}
elsif ($results{skip_all})
{
report( sprintf('All (%d) tests skipped in %s', $results{seen}, $file));
}
else
{
report( find_failures( $file, \%results ) );
}
}
sub report
{
my $message = shift;
print "$message\n";
}
sub find_failures
{
my ($file, $results) = @_;
my $report = create_header($file, @{$results}{qw( max seen ok )});
my $count = 0;
for my $test ( @{ $results->{details} } )
{
$count++;
next if $test->{ok};
$report .= create_test_result( $count, @{ $test }{qw( name reason ) } );
}
return $report;
}
sub create_header
{
my ($file, $expected, $seen, $passed) = @_;
my $failed = $seen - $passed;
return sprintf "File '%s'\nExpected %d / Seen %d / Okay %d / Failed %d\n",
@_, $failed;
}
sub create_test_result
{
my ($number, $name, $reason) = @_;
$name =~ s/^-\s*//;
$reason ||= '';
$reason = " ($reason)" if $reason;
return sprintf "\tTest #%d: %s%s\n", $number, $name, $reason;
}
In practice, I may tweak the formatting somewhat. It might be nice to report skips and surprisingly-passing TODO tests, too. I also might want a flag to end after the first failure, to solve the problem of cascading failures rolling off of the screen. Still, this was a lot simpler than I thought and already makes my life easier.