Add Archive::Tar to the maintainers list
[p5sagit/p5-mst-13.2.git] / lib / Test / Harness.pm
CommitLineData
d667a7e6 1# -*- Mode: cperl; cperl-indent-level: 4 -*-
b82fa0b7 2
a0d0e21e 3package Test::Harness;
4
3c87ea76 5require 5.00405;
13287dd5 6use Test::Harness::Straps;
7use Test::Harness::Assert;
a0d0e21e 8use Exporter;
9use Benchmark;
4633a7c4 10use Config;
760ac839 11use strict;
12
e4fc8a1e 13use vars qw(
14 $VERSION
15 @ISA @EXPORT @EXPORT_OK
16 $Verbose $Switches $Debug
17 $verbose $switches $debug
e4fc8a1e 18 $Curtest
19 $Columns
20 $ML $Last_ML_Print
21 $Strap
22);
23
24=head1 NAME
25
26Test::Harness - Run Perl standard test scripts with statistics
27
28=head1 VERSION
29
c0c1f8c2 30Version 2.48
e4fc8a1e 31
32=cut
33
c0c1f8c2 34$VERSION = "2.48";
4633a7c4 35
9c5c68c8 36# Backwards compatibility for exportable variable names.
5c0604c3 37*verbose = *Verbose;
38*switches = *Switches;
e4fc8a1e 39*debug = *Debug;
9c5c68c8 40
f19ae7a7 41$ENV{HARNESS_ACTIVE} = 1;
c0c1f8c2 42$ENV{HARNESS_VERSION} = $VERSION;
f19ae7a7 43
13287dd5 44END {
45 # For VMS.
46 delete $ENV{HARNESS_ACTIVE};
c0c1f8c2 47 delete $ENV{HARNESS_VERSION};
13287dd5 48}
49
9b0ceca9 50# Some experimental versions of OS/2 build have broken $?
9c5c68c8 51my $Ignore_Exitcode = $ENV{HARNESS_IGNORE_EXITCODE};
52
53my $Files_In_Dir = $ENV{HARNESS_FILELEAK_IN_DIR};
9b0ceca9 54
d5d4ec93 55$Strap = Test::Harness::Straps->new;
17a79f5b 56
3c87ea76 57sub strap { return $Strap };
58
9c5c68c8 59@ISA = ('Exporter');
60@EXPORT = qw(&runtests);
61@EXPORT_OK = qw($verbose $switches);
4633a7c4 62
356733da 63$Verbose = $ENV{HARNESS_VERBOSE} || 0;
e4fc8a1e 64$Debug = $ENV{HARNESS_DEBUG} || 0;
9c5c68c8 65$Switches = "-w";
66$Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
b82fa0b7 67$Columns--; # Some shells have trouble with a full line of text.
68
b82fa0b7 69=head1 SYNOPSIS
70
71 use Test::Harness;
72
73 runtests(@test_files);
74
75=head1 DESCRIPTION
a0d0e21e 76
3c87ea76 77B<STOP!> If all you want to do is write a test script, consider
78using Test::Simple. Test::Harness is the module that reads the
79output from Test::Simple, Test::More and other modules based on
80Test::Builder. You don't need to know about Test::Harness to use
81those modules.
b82fa0b7 82
3c87ea76 83Test::Harness runs tests and expects output from the test in a
84certain format. That format is called TAP, the Test Anything
85Protocol. It is defined in L<Test::Harness::TAP>.
b82fa0b7 86
3c87ea76 87C<Test::Harness::runtests(@tests)> runs all the testscripts named
88as arguments and checks standard output for the expected strings
89in TAP format.
b82fa0b7 90
3c87ea76 91The F<prove> utility is a thin wrapper around Test::Harness.
b82fa0b7 92
13287dd5 93=head2 Taint mode
94
e4fc8a1e 95Test::Harness will honor the C<-T> or C<-t> in the #! line on your
96test files. So if you begin a test with:
13287dd5 97
98 #!perl -T
99
100the test will be run with taint mode on.
101
13287dd5 102=head2 Configuration variables.
103
104These variables can be used to configure the behavior of
105Test::Harness. They are exported on request.
106
107=over 4
108
3c87ea76 109=item C<$Test::Harness::Verbose>
13287dd5 110
3c87ea76 111The package variable C<$Test::Harness::Verbose> is exportable and can be
e4fc8a1e 112used to let C<runtests()> display the standard output of the script
113without altering the behavior otherwise. The F<prove> utility's C<-v>
114flag will set this.
13287dd5 115
3c87ea76 116=item C<$Test::Harness::switches>
13287dd5 117
3c87ea76 118The package variable C<$Test::Harness::switches> is exportable and can be
13287dd5 119used to set perl command line options used for running the test
e4fc8a1e 120script(s). The default value is C<-w>. It overrides C<HARNESS_SWITCHES>.
13287dd5 121
122=back
123
124
b82fa0b7 125=head2 Failure
126
3c87ea76 127When tests fail, analyze the summary report:
b82fa0b7 128
2fe373ce 129 t/base..............ok
130 t/nonumbers.........ok
131 t/ok................ok
132 t/test-harness......ok
133 t/waterloo..........dubious
b82fa0b7 134 Test returned status 3 (wstat 768, 0x300)
135 DIED. FAILED tests 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
136 Failed 10/20 tests, 50.00% okay
137 Failed Test Stat Wstat Total Fail Failed List of Failed
138 -----------------------------------------------------------------------
139 t/waterloo.t 3 768 20 10 50.00% 1 3 5 7 9 11 13 15 17 19
140 Failed 1/5 test scripts, 80.00% okay. 10/44 subtests failed, 77.27% okay.
141
3c87ea76 142Everything passed but F<t/waterloo.t>. It failed 10 of 20 tests and
b82fa0b7 143exited with non-zero status indicating something dubious happened.
144
145The columns in the summary report mean:
146
147=over 4
148
149=item B<Failed Test>
150
151The test file which failed.
152
153=item B<Stat>
154
155If the test exited with non-zero, this is its exit status.
156
157=item B<Wstat>
158
e4fc8a1e 159The wait status of the test.
b82fa0b7 160
161=item B<Total>
162
163Total number of tests expected to run.
164
165=item B<Fail>
166
167Number which failed, either from "not ok" or because they never ran.
168
169=item B<Failed>
170
171Percentage of the total tests which failed.
172
173=item B<List of Failed>
174
175A list of the tests which failed. Successive failures may be
176abbreviated (ie. 15-20 to indicate that tests 15, 16, 17, 18, 19 and
17720 failed).
178
179=back
180
181
182=head2 Functions
183
184Test::Harness currently only has one function, here it is.
185
186=over 4
187
188=item B<runtests>
189
190 my $allok = runtests(@test_files);
191
3c87ea76 192This runs all the given I<@test_files> and divines whether they passed
b82fa0b7 193or failed based on their output to STDOUT (details above). It prints
194out each individual test which failed along with a summary report and
195a how long it all took.
196
3c87ea76 197It returns true if everything was ok. Otherwise it will C<die()> with
d5d4ec93 198one of the messages in the DIAGNOSTICS section.
b82fa0b7 199
b82fa0b7 200=cut
17a79f5b 201
a0d0e21e 202sub runtests {
203 my(@tests) = @_;
9c5c68c8 204
b82fa0b7 205 local ($\, $,);
206
207 my($tot, $failedtests) = _run_all_tests(@tests);
9c5c68c8 208 _show_results($tot, $failedtests);
209
2fe373ce 210 my $ok = _all_ok($tot);
b82fa0b7 211
13287dd5 212 assert(($ok xor keys %$failedtests),
213 q{ok status jives with $failedtests});
b82fa0b7 214
215 return $ok;
216}
217
218=begin _private
219
2fe373ce 220=item B<_all_ok>
221
222 my $ok = _all_ok(\%tot);
223
224Tells you if this test run is overall successful or not.
225
226=cut
227
228sub _all_ok {
229 my($tot) = shift;
230
231 return $tot->{bad} == 0 && ($tot->{max} || $tot->{skipped}) ? 1 : 0;
232}
233
b82fa0b7 234=item B<_globdir>
235
236 my @files = _globdir $dir;
237
238Returns all the files in a directory. This is shorthand for backwards
3c87ea76 239compatibility on systems where C<glob()> doesn't work right.
b82fa0b7 240
241=cut
242
243sub _globdir {
244 opendir DIRH, shift;
245 my @f = readdir DIRH;
246 closedir DIRH;
247
248 return @f;
9c5c68c8 249}
250
b82fa0b7 251=item B<_run_all_tests>
252
253 my($total, $failed) = _run_all_tests(@test_files);
254
e4fc8a1e 255Runs all the given C<@test_files> (as C<runtests()>) but does it
256quietly (no report). $total is a hash ref summary of all the tests
257run. Its keys and values are this:
b82fa0b7 258
259 bonus Number of individual todo tests unexpectedly passed
260 max Number of individual tests ran
261 ok Number of individual tests passed
262 sub_skipped Number of individual tests skipped
2fe373ce 263 todo Number of individual todo tests
b82fa0b7 264
265 files Number of test files ran
266 good Number of test files passed
267 bad Number of test files failed
268 tests Number of test files originally given
269 skipped Number of test files skipped
270
e4fc8a1e 271If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
272got a successful test.
b82fa0b7 273
274$failed is a hash ref of all the test scripts which failed. Each key
275is the name of a test script, each value is another hash representing
276how that script failed. Its keys are these:
9c5c68c8 277
b82fa0b7 278 name Name of the test which failed
279 estat Script's exit value
280 wstat Script's wait status
281 max Number of individual tests
282 failed Number which failed
283 percent Percentage of tests which failed
284 canon List of tests which failed (as string).
285
e4fc8a1e 286C<$failed> should be empty if everything passed.
b82fa0b7 287
288B<NOTE> Currently this function is still noisy. I'm working on it.
289
290=cut
291
3c87ea76 292# Turns on autoflush for the handle passed
293sub _autoflush {
294 my $flushy_fh = shift;
295 my $old_fh = select $flushy_fh;
296 $| = 1;
297 select $old_fh;
298}
299
b82fa0b7 300sub _run_all_tests {
3c87ea76 301 my @tests = @_;
302
303 _autoflush(\*STDOUT);
304 _autoflush(\*STDERR);
305
9c5c68c8 306 my(%failedtests);
307
308 # Test-wide totals.
309 my(%tot) = (
310 bonus => 0,
311 max => 0,
312 ok => 0,
313 files => 0,
314 bad => 0,
315 good => 0,
316 tests => scalar @tests,
317 sub_skipped => 0,
2fe373ce 318 todo => 0,
9c5c68c8 319 skipped => 0,
2fe373ce 320 bench => 0,
9c5c68c8 321 );
774d564b 322
76df5e8f 323 my @dir_files;
324 @dir_files = _globdir $Files_In_Dir if defined $Files_In_Dir;
a0d0e21e 325 my $t_start = new Benchmark;
9c5c68c8 326
13287dd5 327 my $width = _leader_width(@tests);
b82fa0b7 328 foreach my $tfile (@tests) {
5c0604c3 329 $Last_ML_Print = 0; # so each test prints at least once
7a315204 330 my($leader, $ml) = _mk_leader($tfile, $width);
308957f5 331 local $ML = $ml;
e4fc8a1e 332
b82fa0b7 333 print $leader;
9c5c68c8 334
356733da 335 $tot{files}++;
336
308957f5 337 $Strap->{_seen_header} = 0;
3c87ea76 338 if ( $Test::Harness::Debug ) {
339 print "# Running: ", $Strap->_command_line($tfile), "\n";
340 }
0be28027 341 my %results = $Strap->analyze_file($tfile) or
e4fc8a1e 342 do { warn $Strap->{error}, "\n"; next };
308957f5 343
9c5c68c8 344 # state of the current test.
308957f5 345 my @failed = grep { !$results{details}[$_-1]{ok} }
346 1..@{$results{details}};
9c5c68c8 347 my %test = (
308957f5 348 ok => $results{ok},
349 'next' => $Strap->{'next'},
350 max => $results{max},
351 failed => \@failed,
352 bonus => $results{bonus},
353 skipped => $results{skip},
a72fde19 354 skip_reason => $results{skip_reason},
c0bb2de7 355 skip_all => $Strap->{skip_all},
9c5c68c8 356 ml => $ml,
357 );
358
308957f5 359 $tot{bonus} += $results{bonus};
360 $tot{max} += $results{max};
361 $tot{ok} += $results{ok};
362 $tot{todo} += $results{todo};
363 $tot{sub_skipped} += $results{skip};
9c5c68c8 364
308957f5 365 my($estatus, $wstatus) = @results{qw(exit wait)};
b82fa0b7 366
a72fde19 367 if ($results{passing}) {
2fe373ce 368 if ($test{max} and $test{skipped} + $test{bonus}) {
369 my @msg;
370 push(@msg, "$test{skipped}/$test{max} skipped: $test{skip_reason}")
371 if $test{skipped};
372 push(@msg, "$test{bonus}/$test{max} unexpectedly succeeded")
373 if $test{bonus};
f0008e52 374 print "$test{ml}ok\n ".join(', ', @msg)."\n";
2fe373ce 375 } elsif ($test{max}) {
376 print "$test{ml}ok\n";
d5d4ec93 377 } elsif (defined $test{skip_all} and length $test{skip_all}) {
c0bb2de7 378 print "skipped\n all skipped: $test{skip_all}\n";
2fe373ce 379 $tot{skipped}++;
380 } else {
0be28027 381 print "skipped\n all skipped: no reason given\n";
2fe373ce 382 $tot{skipped}++;
383 }
384 $tot{good}++;
385 }
b82fa0b7 386 else {
a72fde19 387 # List unrun tests as failures.
388 if ($test{'next'} <= $test{max}) {
389 push @{$test{failed}}, $test{'next'}..$test{max};
390 }
391 # List overruns as failures.
392 else {
393 my $details = $results{details};
3c87ea76 394 foreach my $overrun ($test{max}+1..@$details) {
a72fde19 395 next unless ref $details->[$overrun-1];
396 push @{$test{failed}}, $overrun
b82fa0b7 397 }
a72fde19 398 }
399
400 if ($wstatus) {
401 $failedtests{$tfile} = _dubious_return(\%test, \%tot,
402 $estatus, $wstatus);
403 $failedtests{$tfile}{name} = $tfile;
404 }
405 elsif($results{seen}) {
c4b2e1b6 406 if (@{$test{failed}} and $test{max}) {
60e33a80 407 my ($txt, $canon) = _canonfailed($test{max},$test{skipped},
b82fa0b7 408 @{$test{failed}});
409 print "$test{ml}$txt";
410 $failedtests{$tfile} = { canon => $canon,
411 max => $test{max},
412 failed => scalar @{$test{failed}},
413 name => $tfile,
414 percent => 100*(scalar @{$test{failed}})/$test{max},
415 estat => '',
416 wstat => '',
417 };
418 } else {
419 print "Don't know which tests failed: got $test{ok} ok, ".
420 "expected $test{max}\n";
421 $failedtests{$tfile} = { canon => '??',
422 max => $test{max},
423 failed => '??',
424 name => $tfile,
425 percent => undef,
426 estat => '',
427 wstat => '',
428 };
429 }
430 $tot{bad}++;
a72fde19 431 } else {
b82fa0b7 432 print "FAILED before any test output arrived\n";
433 $tot{bad}++;
434 $failedtests{$tfile} = { canon => '??',
435 max => '??',
436 failed => '??',
437 name => $tfile,
438 percent => undef,
439 estat => '',
440 wstat => '',
441 };
442 }
443 }
444
2fe373ce 445 if (defined $Files_In_Dir) {
446 my @new_dir_files = _globdir $Files_In_Dir;
447 if (@new_dir_files != @dir_files) {
448 my %f;
449 @f{@new_dir_files} = (1) x @new_dir_files;
450 delete @f{@dir_files};
451 my @f = sort keys %f;
452 print "LEAKED FILES: @f\n";
453 @dir_files = @new_dir_files;
454 }
455 }
3c87ea76 456 } # foreach test
9c5c68c8 457 $tot{bench} = timediff(new Benchmark, $t_start);
d667a7e6 458
13287dd5 459 $Strap->_restore_PERL5LIB;
9c5c68c8 460
461 return(\%tot, \%failedtests);
462}
463
b82fa0b7 464=item B<_mk_leader>
465
7a315204 466 my($leader, $ml) = _mk_leader($test_file, $width);
b82fa0b7 467
3c87ea76 468Generates the 't/foo........' leader for the given C<$test_file> as well
b82fa0b7 469as a similar version which will overwrite the current line (by use of
e4fc8a1e 470\r and such). C<$ml> may be empty if Test::Harness doesn't think you're
2fe373ce 471on TTY.
472
e4fc8a1e 473The C<$width> is the width of the "yada/blah.." string.
b82fa0b7 474
475=cut
476
477sub _mk_leader {
2fe373ce 478 my($te, $width) = @_;
479 chomp($te);
b695f709 480 $te =~ s/\.\w+$/./;
b82fa0b7 481
356733da 482 if ($^O eq 'VMS') { $te =~ s/^.*\.t\./\[.t./s; }
b82fa0b7 483 my $blank = (' ' x 77);
7a315204 484 my $leader = "$te" . '.' x ($width - length($te));
b82fa0b7 485 my $ml = "";
486
487 $ml = "\r$blank\r$leader"
488 if -t STDOUT and not $ENV{HARNESS_NOTTY} and not $Verbose;
489
490 return($leader, $ml);
491}
492
13287dd5 493=item B<_leader_width>
494
495 my($width) = _leader_width(@test_files);
496
497Calculates how wide the leader should be based on the length of the
498longest test name.
499
500=cut
501
502sub _leader_width {
503 my $maxlen = 0;
504 my $maxsuflen = 0;
505 foreach (@_) {
506 my $suf = /\.(\w+)$/ ? $1 : '';
507 my $len = length;
508 my $suflen = length $suf;
509 $maxlen = $len if $len > $maxlen;
510 $maxsuflen = $suflen if $suflen > $maxsuflen;
511 }
356733da 512 # + 3 : we want three dots between the test name and the "ok"
513 return $maxlen + 3 - $maxsuflen;
13287dd5 514}
515
9c5c68c8 516
517sub _show_results {
518 my($tot, $failedtests) = @_;
519
520 my $pct;
521 my $bonusmsg = _bonusmsg($tot);
522
2fe373ce 523 if (_all_ok($tot)) {
524 print "All tests successful$bonusmsg.\n";
525 } elsif (!$tot->{tests}){
526 die "FAILED--no tests were run for some reason.\n";
527 } elsif (!$tot->{max}) {
528 my $blurb = $tot->{tests}==1 ? "script" : "scripts";
529 die "FAILED--$tot->{tests} test $blurb could be run, ".
9c5c68c8 530 "alas--no output ever seen\n";
c07a80fd 531 } else {
2fe373ce 532 $pct = sprintf("%.2f", $tot->{good} / $tot->{tests} * 100);
533 my $percent_ok = 100*$tot->{ok}/$tot->{max};
534 my $subpct = sprintf " %d/%d subtests failed, %.2f%% okay.",
535 $tot->{max} - $tot->{ok}, $tot->{max},
536 $percent_ok;
0a931e4a 537
9c5c68c8 538 my($fmt_top, $fmt) = _create_fmts($failedtests);
0a931e4a 539
2fe373ce 540 # Now write to formats
541 for my $script (sort keys %$failedtests) {
542 $Curtest = $failedtests->{$script};
543 write;
544 }
545 if ($tot->{bad}) {
546 $bonusmsg =~ s/^,\s*//;
547 print "$bonusmsg.\n" if $bonusmsg;
548 die "Failed $tot->{bad}/$tot->{tests} test scripts, $pct% okay.".
9c5c68c8 549 "$subpct\n";
2fe373ce 550 }
c07a80fd 551 }
f0a9308e 552
9c5c68c8 553 printf("Files=%d, Tests=%d, %s\n",
554 $tot->{files}, $tot->{max}, timestr($tot->{bench}, 'nop'));
555}
556
557
3c87ea76 558my %Handlers = (
559 header => \&header_handler,
560 test => \&test_handler,
561 bailout => \&bailout_handler,
562);
563
564$Strap->{callback} = \&strap_callback;
565sub strap_callback {
308957f5 566 my($self, $line, $type, $totals) = @_;
567 print $line if $Verbose;
9c5c68c8 568
308957f5 569 my $meth = $Handlers{$type};
570 $meth->($self, $line, $type, $totals) if $meth;
571};
9c5c68c8 572
9c5c68c8 573
3c87ea76 574sub header_handler {
308957f5 575 my($self, $line, $type, $totals) = @_;
9c5c68c8 576
308957f5 577 warn "Test header seen more than once!\n" if $self->{_seen_header};
9c5c68c8 578
308957f5 579 $self->{_seen_header}++;
9c5c68c8 580
308957f5 581 warn "1..M can only appear at the beginning or end of tests\n"
582 if $totals->{seen} &&
583 $totals->{max} < $totals->{seen};
584};
13287dd5 585
3c87ea76 586sub test_handler {
308957f5 587 my($self, $line, $type, $totals) = @_;
9c5c68c8 588
308957f5 589 my $curr = $totals->{seen};
590 my $next = $self->{'next'};
591 my $max = $totals->{max};
592 my $detail = $totals->{details}[-1];
b82fa0b7 593
308957f5 594 if( $detail->{ok} ) {
5c0604c3 595 _print_ml_less("ok $curr/$max");
356733da 596
308957f5 597 if( $detail->{type} eq 'skip' ) {
a72fde19 598 $totals->{skip_reason} = $detail->{reason}
599 unless defined $totals->{skip_reason};
600 $totals->{skip_reason} = 'various reasons'
601 if $totals->{skip_reason} ne $detail->{reason};
308957f5 602 }
b82fa0b7 603 }
604 else {
308957f5 605 _print_ml("NOK $curr");
b82fa0b7 606 }
b82fa0b7 607
308957f5 608 if( $curr > $next ) {
609 print "Test output counter mismatch [test $curr]\n";
610 }
611 elsif( $curr < $next ) {
612 print "Confused test output: test $curr answered after ".
613 "test ", $next - 1, "\n";
614 }
b82fa0b7 615
308957f5 616};
2fe373ce 617
3c87ea76 618sub bailout_handler {
308957f5 619 my($self, $line, $type, $totals) = @_;
9c5c68c8 620
308957f5 621 die "FAILED--Further testing stopped" .
622 ($self->{bailout_reason} ? ": $self->{bailout_reason}\n" : ".\n");
623};
356733da 624
9c5c68c8 625
308957f5 626sub _print_ml {
627 print join '', $ML, @_ if $ML;
9c5c68c8 628}
629
630
5c0604c3 631# For slow connections, we save lots of bandwidth by printing only once
632# per second.
633sub _print_ml_less {
3c87ea76 634 if ( $Last_ML_Print != time ) {
5c0604c3 635 _print_ml(@_);
636 $Last_ML_Print = time;
637 }
638}
639
9c5c68c8 640sub _bonusmsg {
641 my($tot) = @_;
642
643 my $bonusmsg = '';
644 $bonusmsg = (" ($tot->{bonus} subtest".($tot->{bonus} > 1 ? 's' : '').
2fe373ce 645 " UNEXPECTEDLY SUCCEEDED)")
646 if $tot->{bonus};
9c5c68c8 647
648 if ($tot->{skipped}) {
2fe373ce 649 $bonusmsg .= ", $tot->{skipped} test"
9c5c68c8 650 . ($tot->{skipped} != 1 ? 's' : '');
2fe373ce 651 if ($tot->{sub_skipped}) {
652 $bonusmsg .= " and $tot->{sub_skipped} subtest"
653 . ($tot->{sub_skipped} != 1 ? 's' : '');
654 }
655 $bonusmsg .= ' skipped';
9c5c68c8 656 }
657 elsif ($tot->{sub_skipped}) {
2fe373ce 658 $bonusmsg .= ", $tot->{sub_skipped} subtest"
659 . ($tot->{sub_skipped} != 1 ? 's' : '')
660 . " skipped";
9c5c68c8 661 }
662
663 return $bonusmsg;
664}
665
9c5c68c8 666# Test program go boom.
667sub _dubious_return {
668 my($test, $tot, $estatus, $wstatus) = @_;
669 my ($failed, $canon, $percent) = ('??', '??');
670
671 printf "$test->{ml}dubious\n\tTest returned status $estatus ".
672 "(wstat %d, 0x%x)\n",
673 $wstatus,$wstatus;
674 print "\t\t(VMS status is $estatus)\n" if $^O eq 'VMS';
675
9c5c68c8 676 $tot->{bad}++;
677
678 if ($test->{max}) {
b82fa0b7 679 if ($test->{'next'} == $test->{max} + 1 and not @{$test->{failed}}) {
9c5c68c8 680 print "\tafter all the subtests completed successfully\n";
681 $percent = 0;
2fe373ce 682 $failed = 0; # But we do not set $canon!
9c5c68c8 683 }
684 else {
b82fa0b7 685 push @{$test->{failed}}, $test->{'next'}..$test->{max};
9c5c68c8 686 $failed = @{$test->{failed}};
60e33a80 687 (my $txt, $canon) = _canonfailed($test->{max},$test->{skipped},@{$test->{failed}});
9c5c68c8 688 $percent = 100*(scalar @{$test->{failed}})/$test->{max};
689 print "DIED. ",$txt;
690 }
691 }
692
693 return { canon => $canon, max => $test->{max} || '??',
694 failed => $failed,
66fd8cb9 695 percent => $percent,
9c5c68c8 696 estat => $estatus, wstat => $wstatus,
697 };
698}
699
700
9c5c68c8 701sub _create_fmts {
702 my($failedtests) = @_;
703
b82fa0b7 704 my $failed_str = "Failed Test";
705 my $middle_str = " Stat Wstat Total Fail Failed ";
9c5c68c8 706 my $list_str = "List of Failed";
707
708 # Figure out our longest name string for formatting purposes.
709 my $max_namelen = length($failed_str);
710 foreach my $script (keys %$failedtests) {
711 my $namelen = length $failedtests->{$script}->{name};
712 $max_namelen = $namelen if $namelen > $max_namelen;
713 }
714
715 my $list_len = $Columns - length($middle_str) - $max_namelen;
716 if ($list_len < length($list_str)) {
717 $list_len = length($list_str);
718 $max_namelen = $Columns - length($middle_str) - $list_len;
719 if ($max_namelen < length($failed_str)) {
720 $max_namelen = length($failed_str);
721 $Columns = $max_namelen + length($middle_str) + $list_len;
722 }
723 }
724
725 my $fmt_top = "format STDOUT_TOP =\n"
b82fa0b7 726 . sprintf("%-${max_namelen}s", $failed_str)
9c5c68c8 727 . $middle_str
2fe373ce 728 . $list_str . "\n"
729 . "-" x $Columns
730 . "\n.\n";
9c5c68c8 731
732 my $fmt = "format STDOUT =\n"
2fe373ce 733 . "@" . "<" x ($max_namelen - 1)
b82fa0b7 734 . " @>> @>>>> @>>>> @>>> ^##.##% "
2fe373ce 735 . "^" . "<" x ($list_len - 1) . "\n"
736 . '{ $Curtest->{name}, $Curtest->{estat},'
737 . ' $Curtest->{wstat}, $Curtest->{max},'
738 . ' $Curtest->{failed}, $Curtest->{percent},'
739 . ' $Curtest->{canon}'
740 . "\n}\n"
741 . "~~" . " " x ($Columns - $list_len - 2) . "^"
742 . "<" x ($list_len - 1) . "\n"
743 . '$Curtest->{canon}'
744 . "\n.\n";
9c5c68c8 745
746 eval $fmt_top;
747 die $@ if $@;
748 eval $fmt;
749 die $@ if $@;
750
751 return($fmt_top, $fmt);
752}
753
60e33a80 754sub _canonfailed ($$@) {
89d3b7e2 755 my($max,$skipped,@failed) = @_;
6c31b336 756 my %seen;
757 @failed = sort {$a <=> $b} grep !$seen{$_}++, @failed;
c07a80fd 758 my $failed = @failed;
759 my @result = ();
760 my @canon = ();
761 my $min;
762 my $last = $min = shift @failed;
760ac839 763 my $canon;
c07a80fd 764 if (@failed) {
2fe373ce 765 for (@failed, $failed[-1]) { # don't forget the last one
766 if ($_ > $last+1 || $_ == $last) {
767 if ($min == $last) {
768 push @canon, $last;
769 } else {
770 push @canon, "$min-$last";
771 }
772 $min = $_;
773 }
774 $last = $_;
775 }
776 local $" = ", ";
777 push @result, "FAILED tests @canon\n";
778 $canon = join ' ', @canon;
a0d0e21e 779 } else {
2fe373ce 780 push @result, "FAILED test $last\n";
781 $canon = $last;
a0d0e21e 782 }
c07a80fd 783
784 push @result, "\tFailed $failed/$max tests, ";
e93c2686 785 if ($max) {
786 push @result, sprintf("%.2f",100*(1-$failed/$max)), "% okay";
787 } else {
788 push @result, "?% okay";
789 }
89d3b7e2 790 my $ender = 's' x ($skipped > 1);
e93c2686 791 if ($skipped) {
3c87ea76 792 my $good = $max - $failed - $skipped;
e93c2686 793 my $skipmsg = " (less $skipped skipped test$ender: $good okay, ";
794 if ($max) {
795 my $goodper = sprintf("%.2f",100*($good/$max));
796 $skipmsg .= "$goodper%)";
797 } else {
798 $skipmsg .= "?%)";
799 }
800 push @result, $skipmsg;
801 }
89d3b7e2 802 push @result, "\n";
760ac839 803 my $txt = join "", @result;
804 ($txt, $canon);
a0d0e21e 805}
806
b82fa0b7 807=end _private
9c5c68c8 808
b82fa0b7 809=back
d667a7e6 810
b82fa0b7 811=cut
9c5c68c8 812
9c5c68c8 813
b82fa0b7 8141;
815__END__
9c5c68c8 816
817
cb1a09d0 818=head1 EXPORT
819
e8df9912 820C<&runtests> is exported by Test::Harness by default.
cb1a09d0 821
e4fc8a1e 822C<$verbose>, C<$switches> and C<$debug> are exported upon request.
9c5c68c8 823
cb1a09d0 824=head1 DIAGNOSTICS
825
826=over 4
827
828=item C<All tests successful.\nFiles=%d, Tests=%d, %s>
829
830If all tests are successful some statistics about the performance are
831printed.
832
6c31b336 833=item C<FAILED tests %s\n\tFailed %d/%d tests, %.2f%% okay.>
834
835For any single script that has failing subtests statistics like the
836above are printed.
837
838=item C<Test returned status %d (wstat %d)>
839
9c5c68c8 840Scripts that return a non-zero exit status, both C<$? E<gt>E<gt> 8>
841and C<$?> are printed in a message similar to the above.
6c31b336 842
843=item C<Failed 1 test, %.2f%% okay. %s>
cb1a09d0 844
6c31b336 845=item C<Failed %d/%d tests, %.2f%% okay. %s>
cb1a09d0 846
847If not all tests were successful, the script dies with one of the
848above messages.
849
308957f5 850=item C<FAILED--Further testing stopped: %s>
d667a7e6 851
852If a single subtest decides that further testing will not make sense,
853the script dies with this message.
854
cb1a09d0 855=back
856
c0c1f8c2 857=head1 ENVIRONMENT VARIABLES THAT TEST::HARNESS SETS
858
859Test::Harness sets these before executing the individual tests.
9b0ceca9 860
37ce32a7 861=over 4
862
356733da 863=item C<HARNESS_ACTIVE>
37ce32a7 864
c0c1f8c2 865This is set to a true value. It allows the tests to determine if they
866are being executed through the harness or by any other means.
867
868=item C<HARNESS_VERSION>
869
870This is the version of Test::Harness.
871
872=back
873
874=head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
875
876=over 4
37ce32a7 877
356733da 878=item C<HARNESS_COLUMNS>
9b0ceca9 879
356733da 880This value will be used for the width of the terminal. If it is not
881set then it will default to C<COLUMNS>. If this is not set, it will
882default to 80. Note that users of Bourne-sh based shells will need to
883C<export COLUMNS> for this module to use that variable.
0d0c0d42 884
b82fa0b7 885=item C<HARNESS_COMPILE_TEST>
9636a016 886
37ce32a7 887When true it will make harness attempt to compile the test using
888C<perlcc> before running it.
889
b82fa0b7 890B<NOTE> This currently only works when sitting in the perl source
891directory!
892
e4fc8a1e 893=item C<HARNESS_DEBUG>
894
895If true, Test::Harness will print debugging information about itself as
896it runs the tests. This is different from C<HARNESS_VERBOSE>, which prints
897the output from the test being run. Setting C<$Test::Harness::Debug> will
898override this, or you can use the C<-d> switch in the F<prove> utility.
899
b82fa0b7 900=item C<HARNESS_FILELEAK_IN_DIR>
37ce32a7 901
902When set to the name of a directory, harness will check after each
903test whether new files appeared in that directory, and report them as
17a79f5b 904
905 LEAKED FILES: scr.tmp 0 my.db
906
907If relative, directory name is with respect to the current directory at
908the moment runtests() was called. Putting absolute path into
13287dd5 909C<HARNESS_FILELEAK_IN_DIR> may give more predictable results.
17a79f5b 910
356733da 911=item C<HARNESS_IGNORE_EXITCODE>
912
913Makes harness ignore the exit status of child processes when defined.
914
915=item C<HARNESS_NOTTY>
916
917When set to a true value, forces it to behave as though STDOUT were
918not a console. You may need to set this if you don't want harness to
919output more frequent progress messages using carriage returns. Some
920consoles may not handle carriage returns properly (which results in a
921somewhat messy output).
922
e4fc8a1e 923=item C<HARNESS_PERL>
924
925Usually your tests will be run by C<$^X>, the currently-executing Perl.
926However, you may want to have it run by a different executable, such as
927a threading perl, or a different version.
928
929If you're using the F<prove> utility, you can use the C<--perl> switch.
60af4b93 930
b82fa0b7 931=item C<HARNESS_PERL_SWITCHES>
37ce32a7 932
933Its value will be prepended to the switches used to invoke perl on
b82fa0b7 934each test. For example, setting C<HARNESS_PERL_SWITCHES> to C<-W> will
37ce32a7 935run all tests with all warnings enabled.
936
356733da 937=item C<HARNESS_VERBOSE>
37ce32a7 938
356733da 939If true, Test::Harness will output the verbose results of running
e4fc8a1e 940its tests. Setting C<$Test::Harness::verbose> will override this,
941or you can use the C<-v> switch in the F<prove> utility.
37ce32a7 942
943=back
0a931e4a 944
b82fa0b7 945=head1 EXAMPLE
946
947Here's how Test::Harness tests itself
948
949 $ cd ~/src/devel/Test-Harness
950 $ perl -Mblib -e 'use Test::Harness qw(&runtests $verbose);
951 $verbose=0; runtests @ARGV;' t/*.t
952 Using /home/schwern/src/devel/Test-Harness/blib
953 t/base..............ok
954 t/nonumbers.........ok
955 t/ok................ok
956 t/test-harness......ok
957 All tests successful.
958 Files=4, Tests=24, 2 wallclock secs ( 0.61 cusr + 0.41 csys = 1.02 CPU)
f19ae7a7 959
cb1a09d0 960=head1 SEE ALSO
961
42d29bac 962The included F<prove> utility for running test scripts from the command line,
b82fa0b7 963L<Test> and L<Test::Simple> for writing test scripts, L<Benchmark> for
3c87ea76 964the underlying timing routines, and L<Devel::Cover> for test coverage
b82fa0b7 965analysis.
c07a80fd 966
b82fa0b7 967=head1 TODO
968
969Provide a way of running tests quietly (ie. no printing) for automated
970validation of tests. This will probably take the form of a version
971of runtests() which rather than printing its output returns raw data
356733da 972on the state of the tests. (Partially done in Test::Harness::Straps)
b82fa0b7 973
cf2ab31a 974Document the format.
975
b82fa0b7 976Fix HARNESS_COMPILE_TEST without breaking its core usage.
977
978Figure a way to report test names in the failure summary.
37ce32a7 979
b82fa0b7 980Rework the test summary so long test names are not truncated as badly.
308957f5 981(Partially done with new skip test styles)
b82fa0b7 982
b82fa0b7 983Add option for coverage analysis.
984
cf2ab31a 985Trap STDERR.
986
987Implement Straps total_results()
988
989Remember exit code
990
991Completely redo the print summary code.
992
993Implement Straps callbacks. (experimentally implemented)
994
995Straps->analyze_file() not taint clean, don't know if it can be
996
997Fix that damned VMS nit.
998
999HARNESS_TODOFAIL to display TODO failures
1000
1001Add a test for verbose.
1002
1003Change internal list of test results to a hash.
1004
1005Fix stats display when there's an overrun.
1006
1007Fix so perls with spaces in the filename work.
1008
b82fa0b7 1009Keeping whittling away at _run_all_tests()
1010
b82fa0b7 1011Clean up how the summary is printed. Get rid of those damned formats.
cb1a09d0 1012
1013=head1 BUGS
1014
356733da 1015HARNESS_COMPILE_TEST currently assumes it's run from the Perl source
b82fa0b7 1016directory.
1017
e4fc8a1e 1018Please use the CPAN bug ticketing system at L<http://rt.cpan.org/>.
1019You can also mail bugs, fixes and enhancements to
3c87ea76 1020C<< <bug-test-harness >> at C<< rt.cpan.org> >>.
e4fc8a1e 1021
1022=head1 AUTHORS
1023
3c87ea76 1024Either Tim Bunce or Andreas Koenig, we don't know. What we know for
1025sure is, that it was inspired by Larry Wall's TEST script that came
1026with perl distributions for ages. Numerous anonymous contributors
1027exist. Andreas Koenig held the torch for many years, and then
1028Michael G Schwern.
1029
1030Current maintainer is Andy Lester C<< <andy at petdance.com> >>.
e4fc8a1e 1031
1032=head1 COPYRIGHT
1033
3c87ea76 1034Copyright 2002-2005
1035by Michael G Schwern C<< <schwern at pobox.com> >>,
1036Andy Lester C<< <andy at petdance.com> >>.
e4fc8a1e 1037
1038This program is free software; you can redistribute it and/or
1039modify it under the same terms as Perl itself.
1040
1041See L<http://www.perl.com/perl/misc/Artistic.html>.
1042
cb1a09d0 1043=cut