12 Jan 2005 chromatic   » (Master)

Quieter Test Output:

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.

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!