2009-05-01 Update: Perl module that provides a test harness that runs TAP tests and outputs
JUnit-compatible XML
Here is an experimental program that runs Perl test files and produces the same sort of XML output as the <junit> ant task.
Getting this XML output is helpful when running Perl tests under CruiseControl.
#!/usr/bin/perl
use strict;
use warnings;
use Test::Harness::Straps;
use Time::HiRes qw(gettimeofday tv_interval);
use XML::Generator ':noimport';
my @files = @ARGV;
my $strap = Test::Harness::Straps->new;
my $generator = XML::Generator->new(':pretty');
my @properties = _get_properties($generator);
my $test_results = _run_tests( $strap, $generator, @files );
my $xml = _get_junit_xml( $generator, \@properties, $test_results );
print "$xml\n";
exit;
#-------------------------------------------------------------------------------
sub _get_junit_xml {
my ( $generator, $properties, $test_results ) = @_;
my $system_out = 'system-out';
my $system_err = 'system-err';
my $xml = '';
$xml .= "\n";
$xml .= $generator->testsuite(
{
errors => 0,
failures => $test_results->{total_failures},
name => 'name of the test suite',
tests => $test_results->{total_tests},
'time' => $test_results->{total_time},
},
$generator->properties(@properties),
@{ $test_results->{test_cases} },
$generator->$system_out(),
$generator->$system_err(),
);
return $xml;
}
sub _run_tests {
my ( $strap, $generator, @files ) = @_;
my @test_cases = ();
my $total_tests = 0;
my $total_time = 0;
my $total_failures = 0;
foreach my $test_file (@files) {
my $start_time = [gettimeofday];
my $file_results = $strap->analyze_file($test_file);
my $elapsed_time = tv_interval( $start_time, [gettimeofday] );
$total_time += $elapsed_time;
foreach my $assertion ( @{ $file_results->details } ) {
if ( _skip($assertion) ) {
next;
}
$total_tests++;
$total_failures += _is_failure($assertion);
my $test_case = {
classname => $test_file,
name => $assertion->{name},
'time' => 0,
};
push @test_cases, $generator->testcase($test_case);
}
}
my $test_results = {
total_time => $total_time,
test_cases => \@test_cases,
total_tests => $total_tests,
total_failures => $total_failures,
};
return $test_results;
}
sub _skip {
my $assertion = shift;
return $assertion->{type} =~ / skip | todo /x;
}
sub _is_failure {
my $assertion = shift;
return !$assertion->{ok};
}
sub _get_properties {
my $generator = shift;
my @properties = ();
foreach my $key ( sort keys %ENV ) {
push @properties,
$generator->property( { name => "$key", value => $ENV{$key} } );
}
return @properties;
}
__END__
=head1 NAME
junit_xml.pl - Run Perl tests and get JUnit-style XML output
=head1 SYNOPSIS
junit_xml.pl file1 [ file2 ... ]
=head1 DESCRIPTION
Experimental script to run perl test files and produce the
same XML output as produced by the <junit> ant task.
=head1 DEPENDENCIES
Test::Harness
Time::HiRes
XML::Generator
=head1 BUGS
- Doesn't do anything with the STDERR from tests.
- Doesn't fill in the 'errors' attribute in the <testsuite> element.
- Doesn't handle when all tests in file are skipped (skip_all)
- Doesn't get the elapsed time for each 'test' (i.e. assertion.)
=head1 AUTHOR
Matisse Enzer <matisse@matisse.net>
=head1 COPYRIGHT & LICENSE
Copyright (c) 2007 Matisse Enzer. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=cut
Updates: This post was originally published on 2007-01-21.
2008-05-26: I noticed that Justin Mason has created a better script for converting TAP output to JUnit-style XML
Technorati Tags: Perl, software testing
2 comments:
I know this is an older post, but have you seen the CPAN module, TAP::Harness::JUnit?
Thanks Randy, I did not know about TAP::Harness::JUnit and am glad to see it out there.
Post a Comment