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