ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/Test/Harness.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:15 2005 UTC (21 years, 4 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

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