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 ();
17 # TODO: Emulate at least some of these
20 @ISA @EXPORT @EXPORT_OK
21 $Verbose $Switches $Debug
22 $verbose $switches $debug
34 eval q{use Time::HiRes 'time'};
35 $has_time_hires = !$@;
40 Test::Harness - Run Perl standard test scripts with statistics
50 # Backwards compatibility for exportable variable names.
52 *switches = *Switches;
55 $ENV{HARNESS_ACTIVE} = 1;
56 $ENV{HARNESS_VERSION} = $VERSION;
61 delete $ENV{HARNESS_ACTIVE};
62 delete $ENV{HARNESS_VERSION};
66 @EXPORT = qw(&runtests);
67 @EXPORT_OK = qw(&execute_tests $verbose $switches);
69 $Verbose = $ENV{HARNESS_VERBOSE} || 0;
70 $Debug = $ENV{HARNESS_DEBUG} || 0;
72 $Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
73 $Columns--; # Some shells have trouble with a full line of text.
74 $Timer = $ENV{HARNESS_TIMER} || 0;
75 $Color = $ENV{HARNESS_COLOR} || 0;
81 runtests(@test_files);
85 Although, for historical reasons, the L<Test::Harness> distribution
86 takes its name from this module it now exists only to provide
87 L<TAP::Harness> with an interface that is somewhat backwards compatible
88 with L<Test::Harness> 2.xx. If you're writing new code consider using
89 L<TAP::Harness> directly instead.
91 Emulation is provided for C<runtests> and C<execute_tests> but the
92 pluggable 'Straps' interface that previous versions of L<Test::Harness>
93 supported is not reproduced here. Straps is now available as a stand
94 alone module: L<Test::Harness::Straps>.
96 See L<TAP::Parser> for the main documentation for this distribution.
100 The following functions are available.
102 =head2 runtests( @test_files )
104 This runs all the given I<@test_files> and divines whether they passed
105 or failed based on their output to STDOUT (details above). It prints
106 out each individual test which failed along with a summary report and
107 a how long it all took.
109 It returns true if everything was ok. Otherwise it will C<die()> with
110 one of the messages in the DIAGNOSTICS section.
116 return TAP::Parser::Source::Perl->get_taint(
117 TAP::Parser::Source::Perl->shebang($test) );
121 my ( $harness, $aggregate, @tests ) = @_;
123 # Don't propagate to our children
124 local $ENV{HARNESS_OPTIONS};
128 # Jiggery pokery doesn't appear to work on VMS - so disable it
129 # pending investigation.
130 _aggregate_tests( $harness, $aggregate, @tests );
133 my $path_sep = $Config{path_sep};
134 my $path_pat = qr{$path_sep};
135 my @extra_inc = _filtered_inc();
137 # Supply -I switches in taint mode
140 my ( $args, $test ) = @_;
141 if ( _has_taint( $test->[0] ) ) {
142 push @{ $args->{switches} }, map {"-I$_"} _filtered_inc();
147 my $previous = $ENV{PERL5LIB};
148 local $ENV{PERL5LIB};
151 push @extra_inc, split( $path_pat, $previous );
155 $ENV{PERL5LIB} = join( $path_sep, @extra_inc );
158 _aggregate_tests( $harness, $aggregate, @tests );
162 sub _aggregate_tests {
163 my ( $harness, $aggregate, @tests ) = @_;
165 $harness->aggregate_tests( $aggregate, @tests );
176 my $harness = _new_harness();
177 my $aggregate = TAP::Parser::Aggregator->new();
179 _aggregate( $harness, $aggregate, @tests );
181 $harness->formatter->summary($aggregate);
183 my $total = $aggregate->total;
184 my $passed = $aggregate->passed;
185 my $failed = $aggregate->failed;
187 my @parsers = $aggregate->parsers;
190 for my $parser (@parsers) {
191 $num_bad++ if $parser->has_problems;
195 "Failed %d/%d test programs. %d/%d subtests failed.\n",
196 $num_bad, scalar @parsers, $failed, $total
200 return $total && $total == $passed;
204 my @list = sort { $a <=> $b } @_;
206 my $count = scalar @list;
209 while ( $pos < $count ) {
211 $end++ while $end < $count && $list[$end] <= $list[ $end - 1 ] + 1;
212 push @ranges, ( $end == $pos + 1 )
214 : join( '-', $list[$pos], $list[ $end - 1 ] );
218 return join( ' ', @ranges );
223 if ( defined( my $env_sw = $ENV{HARNESS_PERL_SWITCHES} ) ) {
224 $Switches .= ' ' . $env_sw if ( length($env_sw) );
227 # This is a bit crufty. The switches have all been joined into a
228 # single string so we have to try and recover them.
229 my ( @lib, @switches );
230 for my $opt ( split( /\s+(?=-)/, $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 if ( defined( my $env_opt = $ENV{HARNESS_OPTIONS} ) ) {
255 for my $opt ( split /:/, $env_opt ) {
256 if ( $opt =~ /^j(\d*)$/ ) {
257 $args->{jobs} = $1 || 9;
259 elsif ( $opt eq 'f' ) {
262 elsif ( $opt eq 'c' ) {
266 die "Unknown HARNESS_OPTIONS item: $opt\n";
271 return TAP::Harness->new($args);
274 # Get the parts of @INC which are changed from the stock list AND
275 # preserve reordering of stock directories.
277 my @inc = grep { !ref } @INC; #28567
281 # VMS has a 255-byte limit on the length of %ENV entries, so
282 # toss the ones that involve perl_root, the install location
283 @inc = grep !/perl_root/i, @inc;
288 # Lose any trailing backslashes in the Win32 paths
289 s/[\\\/+]$// foreach @inc;
292 my @default_inc = _default_inc();
297 next if $seen{$dir}++;
299 if ( $dir eq ( $default_inc[0] || '' ) ) {
306 shift @default_inc while @default_inc and $seen{ $default_inc[0] };
314 # Cache this to avoid repeatedly shelling out to Perl.
319 my $perl = $ENV{HARNESS_PERL} || $^X;
320 chomp( @inc = `$perl -le "print join qq[\\n], \@INC"` );
325 sub _check_sequence {
328 while ( my $next = shift @list ) {
329 return if defined $prev && $next <= $prev;
339 # TODO: Handle out option
341 my $harness = _new_harness();
342 my $aggregate = TAP::Parser::Aggregator->new();
358 # Install a callback so we get to see any plans the
366 if ( $plan->directive eq 'SKIP' ) {
374 _aggregate( $harness, $aggregate, @{ $args{tests} } );
376 $tot{bench} = $aggregate->elapsed;
377 my @tests = $aggregate->descriptions;
379 # TODO: Work out the circumstances under which the files
380 # and tests totals can differ.
381 $tot{files} = $tot{tests} = scalar @tests;
383 my %failedtests = ();
384 my %todo_passed = ();
386 for my $test (@tests) {
387 my ($parser) = $aggregate->parsers($test);
389 my @failed = $parser->failed;
391 my $wstat = $parser->wait;
392 my $estat = $parser->exit;
393 my $planned = $parser->tests_planned;
394 my @errors = $parser->parse_errors;
395 my $passed = $parser->passed;
396 my $actual_passed = $parser->actual_passed;
398 my $ok_seq = _check_sequence( $parser->actual_passed );
400 # Duplicate exit, wait status semantics of old version
401 $estat ||= '' unless $wstat;
404 $tot{max} += ( $planned || 0 );
405 $tot{bonus} += $parser->todo_passed;
406 $tot{ok} += $passed > $actual_passed ? $passed : $actual_passed;
407 $tot{sub_skipped} += $parser->skipped;
408 $tot{todo} += $parser->todo;
410 if ( @failed || $estat || @errors ) {
413 my $huh_planned = $planned ? undef : '??';
414 my $huh_errors = $ok_seq ? undef : '??';
416 $failedtests{$test} = {
417 'canon' => $huh_planned
422 'failed' => $huh_planned
425 'max' => $huh_planned || $planned,
434 my @todo = $parser->todo_passed;
436 $todo_passed{$test} = {
437 'canon' => _canon(@todo),
439 'failed' => scalar @todo,
440 'max' => scalar $parser->todo,
447 return ( \%tot, \%failedtests, \%todo_passed );
450 =head2 execute_tests( tests => \@test_files, out => \*FH )
452 Runs all the given C<@test_files> (just like C<runtests()>) but
453 doesn't generate the final report. During testing, progress
454 information will be written to the currently selected output
455 filehandle (usually C<STDOUT>), or to the filehandle given by the
456 C<out> parameter. The I<out> is optional.
458 Returns a list of two values, C<$total> and C<$failed>, describing the
459 results. C<$total> is a hash ref summary of all the tests run. Its
460 keys and values are this:
462 bonus Number of individual todo tests unexpectedly passed
463 max Number of individual tests ran
464 ok Number of individual tests passed
465 sub_skipped Number of individual tests skipped
466 todo Number of individual todo tests
468 files Number of test files ran
469 good Number of test files passed
470 bad Number of test files failed
471 tests Number of test files originally given
472 skipped Number of test files skipped
474 If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
475 got a successful test.
477 C<$failed> is a hash ref of all the test scripts that failed. Each key
478 is the name of a test script, each value is another hash representing
479 how that script failed. Its keys are these:
481 name Name of the test which failed
482 estat Script's exit value
483 wstat Script's wait status
484 max Number of individual tests
485 failed Number which failed
486 canon List of tests which failed (as string).
488 C<$failed> should be empty if everything passed.
497 C<&runtests> is exported by C<Test::Harness> by default.
499 C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are
500 exported upon request.
502 =head1 ENVIRONMENT VARIABLES THAT TAP::HARNESS::COMPATIBLE SETS
504 C<Test::Harness> sets these before executing the individual tests.
508 =item C<HARNESS_ACTIVE>
510 This is set to a true value. It allows the tests to determine if they
511 are being executed through the harness or by any other means.
513 =item C<HARNESS_VERSION>
515 This is the version of C<Test::Harness>.
519 =head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
523 =item C<HARNESS_TIMER>
525 Setting this to true will make the harness display the number of
526 milliseconds each test took. You can also use F<prove>'s C<--timer>
529 =item C<HARNESS_VERBOSE>
531 If true, C<Test::Harness> will output the verbose results of running
532 its tests. Setting C<$Test::Harness::verbose> will override this,
533 or you can use the C<-v> switch in the F<prove> utility.
535 =item C<HARNESS_OPTIONS>
537 Provide additional options to the harness. Currently supported options are:
543 Run <n> (default 9) parallel jobs.
547 Use forked parallelism.
551 Multiple options may be separated by colons:
553 HARNESS_OPTIONS=j9:f make test
563 Please report any bugs or feature requests to
564 C<bug-test-harness at rt.cpan.org>, or through the web interface at
565 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>. I will be
566 notified, and then you'll automatically be notified of progress on your bug
571 Andy Armstrong C<< <andy@hexten.net> >>
573 L<Test::Harness> (on which this module is based) has this attribution:
575 Either Tim Bunce or Andreas Koenig, we don't know. What we know for
576 sure is, that it was inspired by Larry Wall's F<TEST> script that came
577 with perl distributions for ages. Numerous anonymous contributors
578 exist. Andreas Koenig held the torch for many years, and then
581 =head1 LICENCE AND COPYRIGHT
583 Copyright (c) 2007-2008, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved.
585 This module is free software; you can redistribute it and/or
586 modify it under the same terms as Perl itself. See L<perlartistic>.