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