7 use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ );
8 use constant IS_VMS => ( $^O eq 'VMS' );
11 use TAP::Parser::Aggregator ();
12 use TAP::Parser::Source::Perl ();
14 use TAP::Parser::Utils qw( split_shell );
19 # TODO: Emulate at least some of these
22 @ISA @EXPORT @EXPORT_OK
23 $Verbose $Switches $Debug
24 $verbose $switches $debug
37 eval q{use Time::HiRes 'time'};
38 $has_time_hires = !$@;
43 Test::Harness - Run Perl standard test scripts with statistics
53 # Backwards compatibility for exportable variable names.
55 *switches = *Switches;
58 $ENV{HARNESS_ACTIVE} = 1;
59 $ENV{HARNESS_VERSION} = $VERSION;
64 delete $ENV{HARNESS_ACTIVE};
65 delete $ENV{HARNESS_VERSION};
69 @EXPORT = qw(&runtests);
70 @EXPORT_OK = qw(&execute_tests $verbose $switches);
72 $Verbose = $ENV{HARNESS_VERBOSE} || 0;
73 $Debug = $ENV{HARNESS_DEBUG} || 0;
75 $Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
76 $Columns--; # Some shells have trouble with a full line of text.
77 $Timer = $ENV{HARNESS_TIMER} || 0;
78 $Color = $ENV{HARNESS_COLOR} || 0;
79 $IgnoreExit = $ENV{HARNESS_IGNORE_EXIT} || 0;
85 runtests(@test_files);
89 Although, for historical reasons, the L<Test::Harness> distribution
90 takes its name from this module it now exists only to provide
91 L<TAP::Harness> with an interface that is somewhat backwards compatible
92 with L<Test::Harness> 2.xx. If you're writing new code consider using
93 L<TAP::Harness> directly instead.
95 Emulation is provided for C<runtests> and C<execute_tests> but the
96 pluggable 'Straps' interface that previous versions of L<Test::Harness>
97 supported is not reproduced here. Straps is now available as a stand
98 alone module: L<Test::Harness::Straps>.
100 See L<TAP::Parser>, L<TAP::Harness> for the main documentation for this
105 The following functions are available.
107 =head2 runtests( @test_files )
109 This runs all the given I<@test_files> and divines whether they passed
110 or failed based on their output to STDOUT (details above). It prints
111 out each individual test which failed along with a summary report and
112 a how long it all took.
114 It returns true if everything was ok. Otherwise it will C<die()> with
115 one of the messages in the DIAGNOSTICS section.
121 return TAP::Parser::Source::Perl->get_taint(
122 TAP::Parser::Source::Perl->shebang($test) );
126 my ( $harness, $aggregate, @tests ) = @_;
128 # Don't propagate to our children
129 local $ENV{HARNESS_OPTIONS};
131 _apply_extra_INC($harness);
132 _aggregate_tests( $harness, $aggregate, @tests );
135 # Make sure the child seens all the extra junk in @INC
136 sub _apply_extra_INC {
141 my ( $args, $test ) = @_;
142 push @{ $args->{switches} }, map {"-I$_"} _filtered_inc();
147 sub _aggregate_tests {
148 my ( $harness, $aggregate, @tests ) = @_;
150 $harness->aggregate_tests( $aggregate, @tests );
161 my $harness = _new_harness();
162 my $aggregate = TAP::Parser::Aggregator->new();
164 _aggregate( $harness, $aggregate, @tests );
166 $harness->formatter->summary($aggregate);
168 my $total = $aggregate->total;
169 my $passed = $aggregate->passed;
170 my $failed = $aggregate->failed;
172 my @parsers = $aggregate->parsers;
175 for my $parser (@parsers) {
176 $num_bad++ if $parser->has_problems;
180 "Failed %d/%d test programs. %d/%d subtests failed.\n",
181 $num_bad, scalar @parsers, $failed, $total
185 return $total && $total == $passed;
189 my @list = sort { $a <=> $b } @_;
191 my $count = scalar @list;
194 while ( $pos < $count ) {
196 $end++ while $end < $count && $list[$end] <= $list[ $end - 1 ] + 1;
197 push @ranges, ( $end == $pos + 1 )
199 : join( '-', $list[$pos], $list[ $end - 1 ] );
203 return join( ' ', @ranges );
207 my $sub_args = shift || {};
209 my ( @lib, @switches );
210 my @opt = split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} );
211 while ( my $opt = shift @opt ) {
212 if ( $opt =~ /^ -I (.*) $ /x ) {
213 push @lib, length($1) ? $1 : shift @opt;
216 push @switches, $opt;
220 # Do things the old way on VMS...
221 push @lib, _filtered_inc() if IS_VMS;
223 # If $Verbose isn't numeric default to 1. This helps core.
224 my $verbosity = ( $Verbose ? ( $Verbose !~ /\d/ ) ? 1 : $Verbose : 0 );
228 directives => $Directives,
230 switches => \@switches,
232 verbosity => $verbosity,
233 ignore_exit => $IgnoreExit,
236 $args->{stdout} = $sub_args->{out}
237 if exists $sub_args->{out};
239 if ( defined( my $env_opt = $ENV{HARNESS_OPTIONS} ) ) {
240 for my $opt ( split /:/, $env_opt ) {
241 if ( $opt =~ /^j(\d*)$/ ) {
242 $args->{jobs} = $1 || 9;
244 elsif ( $opt eq 'c' ) {
248 die "Unknown HARNESS_OPTIONS item: $opt\n";
253 return TAP::Harness->new($args);
256 # Get the parts of @INC which are changed from the stock list AND
257 # preserve reordering of stock directories.
259 my @inc = grep { !ref } @INC; #28567
263 # VMS has a 255-byte limit on the length of %ENV entries, so
264 # toss the ones that involve perl_root, the install location
265 @inc = grep !/perl_root/i, @inc;
270 # Lose any trailing backslashes in the Win32 paths
271 s/[\\\/]+$// foreach @inc;
274 my @default_inc = _default_inc();
279 next if $seen{$dir}++;
281 if ( $dir eq ( $default_inc[0] || '' ) ) {
288 shift @default_inc while @default_inc and $seen{ $default_inc[0] };
296 # Cache this to avoid repeatedly shelling out to Perl.
302 local $ENV{PERL5LIB};
305 my $perl = $ENV{HARNESS_PERL} || $^X;
307 # Avoid using -l for the benefit of Perl 6
308 chomp( @inc = `$perl -e "print join qq[\\n], \@INC, q[]"` );
313 sub _check_sequence {
316 while ( my $next = shift @list ) {
317 return if defined $prev && $next <= $prev;
327 my $harness = _new_harness( \%args );
328 my $aggregate = TAP::Parser::Aggregator->new();
344 # Install a callback so we get to see any plans the
352 if ( $plan->directive eq 'SKIP' ) {
360 _aggregate( $harness, $aggregate, @{ $args{tests} } );
362 $tot{bench} = $aggregate->elapsed;
363 my @tests = $aggregate->descriptions;
365 # TODO: Work out the circumstances under which the files
366 # and tests totals can differ.
367 $tot{files} = $tot{tests} = scalar @tests;
369 my %failedtests = ();
370 my %todo_passed = ();
372 for my $test (@tests) {
373 my ($parser) = $aggregate->parsers($test);
375 my @failed = $parser->failed;
377 my $wstat = $parser->wait;
378 my $estat = $parser->exit;
379 my $planned = $parser->tests_planned;
380 my @errors = $parser->parse_errors;
381 my $passed = $parser->passed;
382 my $actual_passed = $parser->actual_passed;
384 my $ok_seq = _check_sequence( $parser->actual_passed );
386 # Duplicate exit, wait status semantics of old version
387 $estat ||= '' unless $wstat;
390 $tot{max} += ( $planned || 0 );
391 $tot{bonus} += $parser->todo_passed;
392 $tot{ok} += $passed > $actual_passed ? $passed : $actual_passed;
393 $tot{sub_skipped} += $parser->skipped;
394 $tot{todo} += $parser->todo;
396 if ( @failed || $estat || @errors ) {
399 my $huh_planned = $planned ? undef : '??';
400 my $huh_errors = $ok_seq ? undef : '??';
402 $failedtests{$test} = {
403 'canon' => $huh_planned
408 'failed' => $huh_planned
411 'max' => $huh_planned || $planned,
420 my @todo = $parser->todo_passed;
422 $todo_passed{$test} = {
423 'canon' => _canon(@todo),
425 'failed' => scalar @todo,
426 'max' => scalar $parser->todo,
433 return ( \%tot, \%failedtests, \%todo_passed );
436 =head2 execute_tests( tests => \@test_files, out => \*FH )
438 Runs all the given C<@test_files> (just like C<runtests()>) but
439 doesn't generate the final report. During testing, progress
440 information will be written to the currently selected output
441 filehandle (usually C<STDOUT>), or to the filehandle given by the
442 C<out> parameter. The I<out> is optional.
444 Returns a list of two values, C<$total> and C<$failed>, describing the
445 results. C<$total> is a hash ref summary of all the tests run. Its
446 keys and values are this:
448 bonus Number of individual todo tests unexpectedly passed
449 max Number of individual tests ran
450 ok Number of individual tests passed
451 sub_skipped Number of individual tests skipped
452 todo Number of individual todo tests
454 files Number of test files ran
455 good Number of test files passed
456 bad Number of test files failed
457 tests Number of test files originally given
458 skipped Number of test files skipped
460 If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
461 got a successful test.
463 C<$failed> is a hash ref of all the test scripts that failed. Each key
464 is the name of a test script, each value is another hash representing
465 how that script failed. Its keys are these:
467 name Name of the test which failed
468 estat Script's exit value
469 wstat Script's wait status
470 max Number of individual tests
471 failed Number which failed
472 canon List of tests which failed (as string).
474 C<$failed> should be empty if everything passed.
483 C<&runtests> is exported by C<Test::Harness> by default.
485 C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are
486 exported upon request.
488 =head1 ENVIRONMENT VARIABLES THAT TAP::HARNESS::COMPATIBLE SETS
490 C<Test::Harness> sets these before executing the individual tests.
494 =item C<HARNESS_ACTIVE>
496 This is set to a true value. It allows the tests to determine if they
497 are being executed through the harness or by any other means.
499 =item C<HARNESS_VERSION>
501 This is the version of C<Test::Harness>.
505 =head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
509 =item C<HARNESS_TIMER>
511 Setting this to true will make the harness display the number of
512 milliseconds each test took. You can also use F<prove>'s C<--timer>
515 =item C<HARNESS_VERBOSE>
517 If true, C<Test::Harness> will output the verbose results of running
518 its tests. Setting C<$Test::Harness::verbose> will override this,
519 or you can use the C<-v> switch in the F<prove> utility.
521 =item C<HARNESS_OPTIONS>
523 Provide additional options to the harness. Currently supported options are:
529 Run <n> (default 9) parallel jobs.
533 Use forked parallelism.
537 Multiple options may be separated by colons:
539 HARNESS_OPTIONS=j9:f make test
545 Normally when a Perl program is run in taint mode the contents of the
546 C<PERL5LIB> environment variable do not appear in C<@INC>.
548 Because C<PERL5LIB> is often used during testing to add build
549 directories to C<@INC> C<Test::Harness> (actually
550 L<TAP::Parser::Source::Perl>) passes the names of any directories found
551 in C<PERL5LIB> as -I switches. The net effect of this is that
552 C<PERL5LIB> is honoured even in taint mode.
560 Please report any bugs or feature requests to
561 C<bug-test-harness at rt.cpan.org>, or through the web interface at
562 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>. I will be
563 notified, and then you'll automatically be notified of progress on your bug
568 Andy Armstrong C<< <andy@hexten.net> >>
570 L<Test::Harness> 2.64 (maintained by Andy Lester and on which this
571 module is based) has this attribution:
573 Either Tim Bunce or Andreas Koenig, we don't know. What we know for
574 sure is, that it was inspired by Larry Wall's F<TEST> script that came
575 with perl distributions for ages. Numerous anonymous contributors
576 exist. Andreas Koenig held the torch for many years, and then
579 =head1 LICENCE AND COPYRIGHT
581 Copyright (c) 2007-2008, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved.
583 This module is free software; you can redistribute it and/or
584 modify it under the same terms as Perl itself. See L<perlartistic>.