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
36 eval q{use Time::HiRes 'time'};
37 $has_time_hires = !$@;
42 Test::Harness - Run Perl standard test scripts with statistics
52 # Backwards compatibility for exportable variable names.
54 *switches = *Switches;
57 $ENV{HARNESS_ACTIVE} = 1;
58 $ENV{HARNESS_VERSION} = $VERSION;
63 delete $ENV{HARNESS_ACTIVE};
64 delete $ENV{HARNESS_VERSION};
68 @EXPORT = qw(&runtests);
69 @EXPORT_OK = qw(&execute_tests $verbose $switches);
71 $Verbose = $ENV{HARNESS_VERBOSE} || 0;
72 $Debug = $ENV{HARNESS_DEBUG} || 0;
74 $Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
75 $Columns--; # Some shells have trouble with a full line of text.
76 $Timer = $ENV{HARNESS_TIMER} || 0;
77 $Color = $ENV{HARNESS_COLOR} || 0;
83 runtests(@test_files);
87 Although, for historical reasons, the L<Test::Harness> distribution
88 takes its name from this module it now exists only to provide
89 L<TAP::Harness> with an interface that is somewhat backwards compatible
90 with L<Test::Harness> 2.xx. If you're writing new code consider using
91 L<TAP::Harness> directly instead.
93 Emulation is provided for C<runtests> and C<execute_tests> but the
94 pluggable 'Straps' interface that previous versions of L<Test::Harness>
95 supported is not reproduced here. Straps is now available as a stand
96 alone module: L<Test::Harness::Straps>.
98 See L<TAP::Parser>, L<TAP::Harness> for the main documentation for this
103 The following functions are available.
105 =head2 runtests( @test_files )
107 This runs all the given I<@test_files> and divines whether they passed
108 or failed based on their output to STDOUT (details above). It prints
109 out each individual test which failed along with a summary report and
110 a how long it all took.
112 It returns true if everything was ok. Otherwise it will C<die()> with
113 one of the messages in the DIAGNOSTICS section.
119 return TAP::Parser::Source::Perl->get_taint(
120 TAP::Parser::Source::Perl->shebang($test) );
124 my ( $harness, $aggregate, @tests ) = @_;
126 # Don't propagate to our children
127 local $ENV{HARNESS_OPTIONS};
131 # Jiggery pokery doesn't appear to work on VMS - so disable it
132 # pending investigation.
133 _aggregate_tests( $harness, $aggregate, @tests );
136 my $path_sep = $Config{path_sep};
137 my $path_pat = qr{$path_sep};
138 my @extra_inc = _filtered_inc();
140 # Supply -I switches in taint mode
143 my ( $args, $test ) = @_;
144 if ( _has_taint( $test->[0] ) ) {
145 push @{ $args->{switches} }, map {"-I$_"} _filtered_inc();
150 my $previous = $ENV{PERL5LIB};
151 local $ENV{PERL5LIB};
154 push @extra_inc, split( $path_pat, $previous );
158 $ENV{PERL5LIB} = join( $path_sep, @extra_inc );
161 _aggregate_tests( $harness, $aggregate, @tests );
165 sub _aggregate_tests {
166 my ( $harness, $aggregate, @tests ) = @_;
168 $harness->aggregate_tests( $aggregate, @tests );
179 my $harness = _new_harness();
180 my $aggregate = TAP::Parser::Aggregator->new();
182 _aggregate( $harness, $aggregate, @tests );
184 $harness->formatter->summary($aggregate);
186 my $total = $aggregate->total;
187 my $passed = $aggregate->passed;
188 my $failed = $aggregate->failed;
190 my @parsers = $aggregate->parsers;
193 for my $parser (@parsers) {
194 $num_bad++ if $parser->has_problems;
198 "Failed %d/%d test programs. %d/%d subtests failed.\n",
199 $num_bad, scalar @parsers, $failed, $total
203 return $total && $total == $passed;
207 my @list = sort { $a <=> $b } @_;
209 my $count = scalar @list;
212 while ( $pos < $count ) {
214 $end++ while $end < $count && $list[$end] <= $list[ $end - 1 ] + 1;
215 push @ranges, ( $end == $pos + 1 )
217 : join( '-', $list[$pos], $list[ $end - 1 ] );
221 return join( ' ', @ranges );
225 my $sub_args = shift || {};
227 my ( @lib, @switches );
229 split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} ) )
231 if ( $opt =~ /^ -I (.*) $ /x ) {
235 push @switches, $opt;
239 # Do things the old way on VMS...
240 push @lib, _filtered_inc() if IS_VMS;
242 # If $Verbose isn't numeric default to 1. This helps core.
243 my $verbosity = ( $Verbose ? ( $Verbose !~ /\d/ ) ? 1 : $Verbose : 0 );
247 directives => $Directives,
249 switches => \@switches,
251 verbosity => $verbosity,
254 $args->{stdout} = $sub_args->{out}
255 if exists $sub_args->{out};
257 if ( defined( my $env_opt = $ENV{HARNESS_OPTIONS} ) ) {
258 for my $opt ( split /:/, $env_opt ) {
259 if ( $opt =~ /^j(\d*)$/ ) {
260 $args->{jobs} = $1 || 9;
262 elsif ( $opt eq 'f' ) {
265 elsif ( $opt eq 'c' ) {
269 die "Unknown HARNESS_OPTIONS item: $opt\n";
274 return TAP::Harness->new($args);
277 # Get the parts of @INC which are changed from the stock list AND
278 # preserve reordering of stock directories.
280 my @inc = grep { !ref } @INC; #28567
284 # VMS has a 255-byte limit on the length of %ENV entries, so
285 # toss the ones that involve perl_root, the install location
286 @inc = grep !/perl_root/i, @inc;
291 # Lose any trailing backslashes in the Win32 paths
292 s/[\\\/+]$// foreach @inc;
295 my @default_inc = _default_inc();
300 next if $seen{$dir}++;
302 if ( $dir eq ( $default_inc[0] || '' ) ) {
309 shift @default_inc while @default_inc and $seen{ $default_inc[0] };
317 # Cache this to avoid repeatedly shelling out to Perl.
322 my $perl = $ENV{HARNESS_PERL} || $^X;
323 chomp( @inc = `$perl -le "print join qq[\\n], \@INC"` );
328 sub _check_sequence {
331 while ( my $next = shift @list ) {
332 return if defined $prev && $next <= $prev;
342 my $harness = _new_harness( \%args );
343 my $aggregate = TAP::Parser::Aggregator->new();
359 # Install a callback so we get to see any plans the
367 if ( $plan->directive eq 'SKIP' ) {
375 _aggregate( $harness, $aggregate, @{ $args{tests} } );
377 $tot{bench} = $aggregate->elapsed;
378 my @tests = $aggregate->descriptions;
380 # TODO: Work out the circumstances under which the files
381 # and tests totals can differ.
382 $tot{files} = $tot{tests} = scalar @tests;
384 my %failedtests = ();
385 my %todo_passed = ();
387 for my $test (@tests) {
388 my ($parser) = $aggregate->parsers($test);
390 my @failed = $parser->failed;
392 my $wstat = $parser->wait;
393 my $estat = $parser->exit;
394 my $planned = $parser->tests_planned;
395 my @errors = $parser->parse_errors;
396 my $passed = $parser->passed;
397 my $actual_passed = $parser->actual_passed;
399 my $ok_seq = _check_sequence( $parser->actual_passed );
401 # Duplicate exit, wait status semantics of old version
402 $estat ||= '' unless $wstat;
405 $tot{max} += ( $planned || 0 );
406 $tot{bonus} += $parser->todo_passed;
407 $tot{ok} += $passed > $actual_passed ? $passed : $actual_passed;
408 $tot{sub_skipped} += $parser->skipped;
409 $tot{todo} += $parser->todo;
411 if ( @failed || $estat || @errors ) {
414 my $huh_planned = $planned ? undef : '??';
415 my $huh_errors = $ok_seq ? undef : '??';
417 $failedtests{$test} = {
418 'canon' => $huh_planned
423 'failed' => $huh_planned
426 'max' => $huh_planned || $planned,
435 my @todo = $parser->todo_passed;
437 $todo_passed{$test} = {
438 'canon' => _canon(@todo),
440 'failed' => scalar @todo,
441 'max' => scalar $parser->todo,
448 return ( \%tot, \%failedtests, \%todo_passed );
451 =head2 execute_tests( tests => \@test_files, out => \*FH )
453 Runs all the given C<@test_files> (just like C<runtests()>) but
454 doesn't generate the final report. During testing, progress
455 information will be written to the currently selected output
456 filehandle (usually C<STDOUT>), or to the filehandle given by the
457 C<out> parameter. The I<out> is optional.
459 Returns a list of two values, C<$total> and C<$failed>, describing the
460 results. C<$total> is a hash ref summary of all the tests run. Its
461 keys and values are this:
463 bonus Number of individual todo tests unexpectedly passed
464 max Number of individual tests ran
465 ok Number of individual tests passed
466 sub_skipped Number of individual tests skipped
467 todo Number of individual todo tests
469 files Number of test files ran
470 good Number of test files passed
471 bad Number of test files failed
472 tests Number of test files originally given
473 skipped Number of test files skipped
475 If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
476 got a successful test.
478 C<$failed> is a hash ref of all the test scripts that failed. Each key
479 is the name of a test script, each value is another hash representing
480 how that script failed. Its keys are these:
482 name Name of the test which failed
483 estat Script's exit value
484 wstat Script's wait status
485 max Number of individual tests
486 failed Number which failed
487 canon List of tests which failed (as string).
489 C<$failed> should be empty if everything passed.
498 C<&runtests> is exported by C<Test::Harness> by default.
500 C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are
501 exported upon request.
503 =head1 ENVIRONMENT VARIABLES THAT TAP::HARNESS::COMPATIBLE SETS
505 C<Test::Harness> sets these before executing the individual tests.
509 =item C<HARNESS_ACTIVE>
511 This is set to a true value. It allows the tests to determine if they
512 are being executed through the harness or by any other means.
514 =item C<HARNESS_VERSION>
516 This is the version of C<Test::Harness>.
520 =head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
524 =item C<HARNESS_TIMER>
526 Setting this to true will make the harness display the number of
527 milliseconds each test took. You can also use F<prove>'s C<--timer>
530 =item C<HARNESS_VERBOSE>
532 If true, C<Test::Harness> will output the verbose results of running
533 its tests. Setting C<$Test::Harness::verbose> will override this,
534 or you can use the C<-v> switch in the F<prove> utility.
536 =item C<HARNESS_OPTIONS>
538 Provide additional options to the harness. Currently supported options are:
544 Run <n> (default 9) parallel jobs.
548 Use forked parallelism.
552 Multiple options may be separated by colons:
554 HARNESS_OPTIONS=j9:f make test
560 Normally when a Perl program is run in taint mode the contents of the
561 C<PERL5LIB> environment variable do not appear in C<@INC>.
563 Because C<PERL5LIB> is often used during testing to add build
564 directories to C<@INC> C<Test::Harness> (actually
565 L<TAP::Parser::Source::Perl>) passes the names of any directories found
566 in C<PERL5LIB> as -I switches. The net effect of this is that
567 C<PERL5LIB> is honoured even in taint mode.
575 Please report any bugs or feature requests to
576 C<bug-test-harness at rt.cpan.org>, or through the web interface at
577 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>. I will be
578 notified, and then you'll automatically be notified of progress on your bug
583 Andy Armstrong C<< <andy@hexten.net> >>
585 L<Test::Harness> 2.64 (maintained by Andy Lester and on which this
586 module is based) has this attribution:
588 Either Tim Bunce or Andreas Koenig, we don't know. What we know for
589 sure is, that it was inspired by Larry Wall's F<TEST> script that came
590 with perl distributions for ages. Numerous anonymous contributors
591 exist. Andreas Koenig held the torch for many years, and then
594 =head1 LICENCE AND COPYRIGHT
596 Copyright (c) 2007-2008, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved.
598 This module is free software; you can redistribute it and/or
599 modify it under the same terms as Perl itself. See L<perlartistic>.