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