This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Move Test::Harness from ext/ to cpan/
[perl5.git] / cpan / Test-Harness / lib / Test / Harness.pm
CommitLineData
a0d0e21e
LW
1package Test::Harness;
2
3c87ea76 3require 5.00405;
b965d173 4
760ac839
LW
5use strict;
6
b965d173
NC
7use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ );
8use constant IS_VMS => ( $^O eq 'VMS' );
9
10use TAP::Harness ();
11use TAP::Parser::Aggregator ();
12use TAP::Parser::Source::Perl ();
ca09b021 13
bd3ac2f1
SP
14use TAP::Parser::Utils qw( split_shell );
15
b965d173
NC
16use Config;
17use Exporter;
18
19# TODO: Emulate at least some of these
e4fc8a1e 20use vars qw(
b965d173
NC
21 $VERSION
22 @ISA @EXPORT @EXPORT_OK
23 $Verbose $Switches $Debug
24 $verbose $switches $debug
25 $Columns
53bc175b 26 $Color
b965d173
NC
27 $Directives
28 $Timer
29 $Strap
30 $has_time_hires
f7c69158 31 $IgnoreExit
e4fc8a1e
RGS
32);
33
b965d173
NC
34# $ML $Last_ML_Print
35
43ef773b 36BEGIN {
5b1ebecd 37 eval q{use Time::HiRes 'time'};
43ef773b
RGS
38 $has_time_hires = !$@;
39}
40
e4fc8a1e
RGS
41=head1 NAME
42
43Test::Harness - Run Perl standard test scripts with statistics
44
45=head1 VERSION
46
a39e16d8 47Version 3.17
e4fc8a1e
RGS
48
49=cut
50
a39e16d8 51$VERSION = '3.17';
4633a7c4 52
9c5c68c8 53# Backwards compatibility for exportable variable names.
5c0604c3
MS
54*verbose = *Verbose;
55*switches = *Switches;
e4fc8a1e 56*debug = *Debug;
9c5c68c8 57
b965d173 58$ENV{HARNESS_ACTIVE} = 1;
c0c1f8c2 59$ENV{HARNESS_VERSION} = $VERSION;
f19ae7a7 60
13287dd5 61END {
b965d173 62
13287dd5
MS
63 # For VMS.
64 delete $ENV{HARNESS_ACTIVE};
c0c1f8c2 65 delete $ENV{HARNESS_VERSION};
13287dd5
MS
66}
67
b965d173 68@ISA = ('Exporter');
9c5c68c8 69@EXPORT = qw(&runtests);
20f9f807 70@EXPORT_OK = qw(&execute_tests $verbose $switches);
4633a7c4 71
b965d173
NC
72$Verbose = $ENV{HARNESS_VERBOSE} || 0;
73$Debug = $ENV{HARNESS_DEBUG} || 0;
5b1ebecd 74$Switches = '-w';
b965d173
NC
75$Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
76$Columns--; # Some shells have trouble with a full line of text.
f7c69158
NC
77$Timer = $ENV{HARNESS_TIMER} || 0;
78$Color = $ENV{HARNESS_COLOR} || 0;
79$IgnoreExit = $ENV{HARNESS_IGNORE_EXIT} || 0;
b82fa0b7 80
b82fa0b7
MS
81=head1 SYNOPSIS
82
83 use Test::Harness;
84
85 runtests(@test_files);
86
87=head1 DESCRIPTION
a0d0e21e 88
b965d173
NC
89Although, for historical reasons, the L<Test::Harness> distribution
90takes its name from this module it now exists only to provide
91L<TAP::Harness> with an interface that is somewhat backwards compatible
92with L<Test::Harness> 2.xx. If you're writing new code consider using
93L<TAP::Harness> directly instead.
b82fa0b7 94
b965d173
NC
95Emulation is provided for C<runtests> and C<execute_tests> but the
96pluggable 'Straps' interface that previous versions of L<Test::Harness>
97supported is not reproduced here. Straps is now available as a stand
98alone module: L<Test::Harness::Straps>.
b82fa0b7 99
bd3ac2f1
SP
100See L<TAP::Parser>, L<TAP::Harness> for the main documentation for this
101distribution.
13287dd5 102
b965d173 103=head1 FUNCTIONS
13287dd5 104
b965d173 105The following functions are available.
13287dd5 106
b965d173 107=head2 runtests( @test_files )
13287dd5 108
b965d173
NC
109This runs all the given I<@test_files> and divines whether they passed
110or failed based on their output to STDOUT (details above). It prints
111out each individual test which failed along with a summary report and
112a how long it all took.
13287dd5 113
b965d173
NC
114It returns true if everything was ok. Otherwise it will C<die()> with
115one of the messages in the DIAGNOSTICS section.
13287dd5 116
b965d173 117=cut
13287dd5 118
b965d173
NC
119sub _has_taint {
120 my $test = shift;
121 return TAP::Parser::Source::Perl->get_taint(
122 TAP::Parser::Source::Perl->shebang($test) );
123}
13287dd5 124
b965d173
NC
125sub _aggregate {
126 my ( $harness, $aggregate, @tests ) = @_;
13287dd5 127
b965d173
NC
128 # Don't propagate to our children
129 local $ENV{HARNESS_OPTIONS};
13287dd5 130
bdaf8c65
SH
131 _apply_extra_INC($harness);
132 _aggregate_tests( $harness, $aggregate, @tests );
133}
13287dd5 134
bdaf8c65
SH
135# Make sure the child seens all the extra junk in @INC
136sub _apply_extra_INC {
137 my $harness = shift;
13287dd5 138
bdaf8c65
SH
139 $harness->callback(
140 parser_args => sub {
141 my ( $args, $test ) = @_;
142 push @{ $args->{switches} }, map {"-I$_"} _filtered_inc();
b965d173 143 }
bdaf8c65 144 );
b965d173 145}
b82fa0b7 146
53bc175b
RGS
147sub _aggregate_tests {
148 my ( $harness, $aggregate, @tests ) = @_;
149 $aggregate->start();
150 $harness->aggregate_tests( $aggregate, @tests );
151 $aggregate->stop();
152
153}
154
b965d173
NC
155sub runtests {
156 my @tests = @_;
b82fa0b7 157
b965d173
NC
158 # shield against -l
159 local ( $\, $, );
b82fa0b7 160
b965d173
NC
161 my $harness = _new_harness();
162 my $aggregate = TAP::Parser::Aggregator->new();
b82fa0b7 163
b965d173 164 _aggregate( $harness, $aggregate, @tests );
b82fa0b7 165
b965d173 166 $harness->formatter->summary($aggregate);
b82fa0b7 167
b965d173
NC
168 my $total = $aggregate->total;
169 my $passed = $aggregate->passed;
170 my $failed = $aggregate->failed;
b82fa0b7 171
b965d173 172 my @parsers = $aggregate->parsers;
b82fa0b7 173
b965d173
NC
174 my $num_bad = 0;
175 for my $parser (@parsers) {
176 $num_bad++ if $parser->has_problems;
177 }
b82fa0b7 178
b965d173
NC
179 die(sprintf(
180 "Failed %d/%d test programs. %d/%d subtests failed.\n",
181 $num_bad, scalar @parsers, $failed, $total
182 )
183 ) if $num_bad;
b82fa0b7 184
b965d173
NC
185 return $total && $total == $passed;
186}
b82fa0b7 187
b965d173
NC
188sub _canon {
189 my @list = sort { $a <=> $b } @_;
190 my @ranges = ();
191 my $count = scalar @list;
192 my $pos = 0;
193
194 while ( $pos < $count ) {
195 my $end = $pos + 1;
196 $end++ while $end < $count && $list[$end] <= $list[ $end - 1 ] + 1;
197 push @ranges, ( $end == $pos + 1 )
198 ? $list[$pos]
199 : join( '-', $list[$pos], $list[ $end - 1 ] );
200 $pos = $end;
201 }
b82fa0b7 202
b965d173
NC
203 return join( ' ', @ranges );
204}
b82fa0b7 205
b965d173 206sub _new_harness {
41d86c6b 207 my $sub_args = shift || {};
b82fa0b7 208
b965d173 209 my ( @lib, @switches );
a39e16d8
SP
210 my @opt = split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} );
211 while ( my $opt = shift @opt ) {
b965d173 212 if ( $opt =~ /^ -I (.*) $ /x ) {
a39e16d8 213 push @lib, length($1) ? $1 : shift @opt;
b965d173
NC
214 }
215 else {
216 push @switches, $opt;
217 }
218 }
b82fa0b7 219
b965d173
NC
220 # Do things the old way on VMS...
221 push @lib, _filtered_inc() if IS_VMS;
222
53bc175b
RGS
223 # If $Verbose isn't numeric default to 1. This helps core.
224 my $verbosity = ( $Verbose ? ( $Verbose !~ /\d/ ) ? 1 : $Verbose : 0 );
225
b965d173 226 my $args = {
f7c69158
NC
227 timer => $Timer,
228 directives => $Directives,
229 lib => \@lib,
230 switches => \@switches,
231 color => $Color,
232 verbosity => $verbosity,
233 ignore_exit => $IgnoreExit,
b965d173
NC
234 };
235
41d86c6b
SP
236 $args->{stdout} = $sub_args->{out}
237 if exists $sub_args->{out};
238
b965d173
NC
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;
243 }
53bc175b
RGS
244 elsif ( $opt eq 'c' ) {
245 $args->{color} = 1;
246 }
b965d173
NC
247 else {
248 die "Unknown HARNESS_OPTIONS item: $opt\n";
249 }
250 }
251 }
b82fa0b7 252
b965d173
NC
253 return TAP::Harness->new($args);
254}
b82fa0b7 255
b965d173
NC
256# Get the parts of @INC which are changed from the stock list AND
257# preserve reordering of stock directories.
258sub _filtered_inc {
259 my @inc = grep { !ref } @INC; #28567
b82fa0b7 260
b965d173 261 if (IS_VMS) {
b82fa0b7 262
b965d173
NC
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;
b82fa0b7 266
b965d173
NC
267 }
268 elsif (IS_WIN32) {
b82fa0b7 269
b965d173 270 # Lose any trailing backslashes in the Win32 paths
27fc0087 271 s/[\\\/]+$// foreach @inc;
b965d173 272 }
b82fa0b7 273
b965d173 274 my @default_inc = _default_inc();
b82fa0b7 275
b965d173
NC
276 my @new_inc;
277 my %seen;
278 for my $dir (@inc) {
279 next if $seen{$dir}++;
17a79f5b 280
b965d173
NC
281 if ( $dir eq ( $default_inc[0] || '' ) ) {
282 shift @default_inc;
283 }
284 else {
285 push @new_inc, $dir;
286 }
9c5c68c8 287
b965d173
NC
288 shift @default_inc while @default_inc and $seen{ $default_inc[0] };
289 }
b82fa0b7 290
b965d173
NC
291 return @new_inc;
292}
9c5c68c8 293
b965d173 294{
b82fa0b7 295
b965d173
NC
296 # Cache this to avoid repeatedly shelling out to Perl.
297 my @inc;
b82fa0b7 298
b965d173
NC
299 sub _default_inc {
300 return @inc if @inc;
bdaf8c65
SH
301
302 local $ENV{PERL5LIB};
303 local $ENV{PERLLIB};
304
b965d173 305 my $perl = $ENV{HARNESS_PERL} || $^X;
bdaf8c65
SH
306
307 # Avoid using -l for the benefit of Perl 6
308 chomp( @inc = `$perl -e "print join qq[\\n], \@INC, q[]"` );
b965d173 309 return @inc;
d1ef75db 310 }
b82fa0b7
MS
311}
312
b965d173
NC
313sub _check_sequence {
314 my @list = @_;
315 my $prev;
316 while ( my $next = shift @list ) {
317 return if defined $prev && $next <= $prev;
318 $prev = $next;
319 }
2fe373ce 320
b965d173 321 return 1;
2fe373ce
MS
322}
323
b965d173
NC
324sub execute_tests {
325 my %args = @_;
b82fa0b7 326
41d86c6b 327 my $harness = _new_harness( \%args );
b965d173
NC
328 my $aggregate = TAP::Parser::Aggregator->new();
329
330 my %tot = (
331 bonus => 0,
332 max => 0,
333 ok => 0,
334 bad => 0,
335 good => 0,
336 files => 0,
337 tests => 0,
338 sub_skipped => 0,
339 todo => 0,
340 skipped => 0,
341 bench => undef,
342 );
343
344 # Install a callback so we get to see any plans the
345 # harness executes.
346 $harness->callback(
347 made_parser => sub {
348 my $parser = shift;
349 $parser->callback(
350 plan => sub {
351 my $plan = shift;
352 if ( $plan->directive eq 'SKIP' ) {
353 $tot{skipped}++;
354 }
355 }
356 );
357 }
358 );
359
360 _aggregate( $harness, $aggregate, @{ $args{tests} } );
361
362 $tot{bench} = $aggregate->elapsed;
363 my @tests = $aggregate->descriptions;
364
365 # TODO: Work out the circumstances under which the files
366 # and tests totals can differ.
367 $tot{files} = $tot{tests} = scalar @tests;
368
369 my %failedtests = ();
370 my %todo_passed = ();
371
372 for my $test (@tests) {
373 my ($parser) = $aggregate->parsers($test);
374
375 my @failed = $parser->failed;
376
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;
383
384 my $ok_seq = _check_sequence( $parser->actual_passed );
385
386 # Duplicate exit, wait status semantics of old version
387 $estat ||= '' unless $wstat;
388 $wstat ||= '';
389
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;
395
396 if ( @failed || $estat || @errors ) {
397 $tot{bad}++;
398
399 my $huh_planned = $planned ? undef : '??';
400 my $huh_errors = $ok_seq ? undef : '??';
401
402 $failedtests{$test} = {
403 'canon' => $huh_planned
404 || $huh_errors
405 || _canon(@failed)
406 || '??',
407 'estat' => $estat,
408 'failed' => $huh_planned
409 || $huh_errors
410 || scalar @failed,
411 'max' => $huh_planned || $planned,
412 'name' => $test,
413 'wstat' => $wstat
414 };
415 }
416 else {
417 $tot{good}++;
418 }
b82fa0b7 419
b965d173
NC
420 my @todo = $parser->todo_passed;
421 if (@todo) {
422 $todo_passed{$test} = {
423 'canon' => _canon(@todo),
424 'estat' => $estat,
425 'failed' => scalar @todo,
426 'max' => scalar $parser->todo,
427 'name' => $test,
428 'wstat' => $wstat
429 };
430 }
431 }
b82fa0b7 432
b965d173 433 return ( \%tot, \%failedtests, \%todo_passed );
9c5c68c8
MS
434}
435
20f9f807 436=head2 execute_tests( tests => \@test_files, out => \*FH )
b82fa0b7 437
20f9f807
RGS
438Runs all the given C<@test_files> (just like C<runtests()>) but
439doesn't generate the final report. During testing, progress
440information will be written to the currently selected output
441filehandle (usually C<STDOUT>), or to the filehandle given by the
442C<out> parameter. The I<out> is optional.
b82fa0b7 443
20f9f807
RGS
444Returns a list of two values, C<$total> and C<$failed>, describing the
445results. C<$total> is a hash ref summary of all the tests run. Its
446keys and values are this:
b82fa0b7
MS
447
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
2fe373ce 452 todo Number of individual todo tests
b82fa0b7
MS
453
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
459
e4fc8a1e
RGS
460If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
461got a successful test.
b82fa0b7 462
20f9f807 463C<$failed> is a hash ref of all the test scripts that failed. Each key
b82fa0b7
MS
464is the name of a test script, each value is another hash representing
465how that script failed. Its keys are these:
9c5c68c8 466
b82fa0b7
MS
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
b82fa0b7
MS
472 canon List of tests which failed (as string).
473
e4fc8a1e 474C<$failed> should be empty if everything passed.
b82fa0b7 475
b82fa0b7
MS
476=cut
477
b82fa0b7
MS
4781;
479__END__
9c5c68c8 480
cb1a09d0
AD
481=head1 EXPORT
482
b965d173 483C<&runtests> is exported by C<Test::Harness> by default.
cb1a09d0 484
20f9f807
RGS
485C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are
486exported upon request.
9c5c68c8 487
b965d173 488=head1 ENVIRONMENT VARIABLES THAT TAP::HARNESS::COMPATIBLE SETS
c0c1f8c2 489
b965d173 490C<Test::Harness> sets these before executing the individual tests.
9b0ceca9 491
37ce32a7
MS
492=over 4
493
356733da 494=item C<HARNESS_ACTIVE>
37ce32a7 495
c0c1f8c2
RGS
496This is set to a true value. It allows the tests to determine if they
497are being executed through the harness or by any other means.
498
499=item C<HARNESS_VERSION>
500
b965d173 501This is the version of C<Test::Harness>.
c0c1f8c2
RGS
502
503=back
504
505=head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
506
507=over 4
37ce32a7 508
ea5423ed
NC
509=item C<HARNESS_TIMER>
510
511Setting this to true will make the harness display the number of
512milliseconds each test took. You can also use F<prove>'s C<--timer>
513switch.
514
356733da 515=item C<HARNESS_VERBOSE>
37ce32a7 516
b965d173 517If true, C<Test::Harness> will output the verbose results of running
5b1ebecd
SP
518its tests. Setting C<$Test::Harness::verbose> will override this,
519or you can use the C<-v> switch in the F<prove> utility.
520
b965d173 521=item C<HARNESS_OPTIONS>
5b1ebecd 522
b965d173 523Provide additional options to the harness. Currently supported options are:
5b1ebecd 524
b965d173 525=over
5b1ebecd 526
b965d173 527=item C<< j<n> >>
5b1ebecd 528
b965d173 529Run <n> (default 9) parallel jobs.
b82fa0b7 530
b965d173 531=item C<< f >>
37ce32a7 532
b965d173 533Use forked parallelism.
b82fa0b7 534
b965d173 535=back
cf2ab31a 536
b965d173 537Multiple options may be separated by colons:
cf2ab31a 538
b965d173 539 HARNESS_OPTIONS=j9:f make test
cf2ab31a 540
b965d173 541=back
cf2ab31a 542
bd3ac2f1
SP
543=head1 Taint Mode
544
545Normally when a Perl program is run in taint mode the contents of the
546C<PERL5LIB> environment variable do not appear in C<@INC>.
547
548Because C<PERL5LIB> is often used during testing to add build
549directories to C<@INC> C<Test::Harness> (actually
550L<TAP::Parser::Source::Perl>) passes the names of any directories found
551in C<PERL5LIB> as -I switches. The net effect of this is that
552C<PERL5LIB> is honoured even in taint mode.
553
b965d173 554=head1 SEE ALSO
b82fa0b7 555
b965d173 556L<TAP::Harness>
cb1a09d0
AD
557
558=head1 BUGS
559
20f9f807
RGS
560Please report any bugs or feature requests to
561C<bug-test-harness at rt.cpan.org>, or through the web interface at
b965d173
NC
562L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>. I will be
563notified, and then you'll automatically be notified of progress on your bug
564as I make changes.
e4fc8a1e
RGS
565
566=head1 AUTHORS
567
b965d173 568Andy Armstrong C<< <andy@hexten.net> >>
3c87ea76 569
bd3ac2f1
SP
570L<Test::Harness> 2.64 (maintained by Andy Lester and on which this
571module is based) has this attribution:
e4fc8a1e 572
b965d173
NC
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
577 Michael G Schwern.
e4fc8a1e 578
b965d173 579=head1 LICENCE AND COPYRIGHT
e4fc8a1e 580
53bc175b 581Copyright (c) 2007-2008, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved.
e4fc8a1e 582
b965d173
NC
583This module is free software; you can redistribute it and/or
584modify it under the same terms as Perl itself. See L<perlartistic>.
e4fc8a1e 585