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. =cutUpdates: 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