root/inc/Test/Harness.pm

Revision 6758, 30.5 kB (checked in by Darren_Duncan, 3 years ago)

converted tabs to 8 spaces each in inc/Test/Harness.pm and inc/Test/Harness/Straps.pm

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