Recode the naughty binary bytes ([\x00-\x08\x0b-\x1f\x7f-\xff])
[p5sagit/p5-mst-13.2.git] / lib / Test / Harness.pm
CommitLineData
d667a7e6 1# -*- Mode: cperl; cperl-indent-level: 4 -*-
a0d0e21e 2package Test::Harness;
3
17f410f9 4use 5.005_64;
a0d0e21e 5use Exporter;
6use Benchmark;
4633a7c4 7use Config;
6c31b336 8use FileHandle;
760ac839 9use strict;
10
17f410f9 11our($VERSION, $verbose, $switches, $have_devel_corestack, $curtest,
0a931e4a 12 $columns, @ISA, @EXPORT, @EXPORT_OK);
c0ee6f5c 13$have_devel_corestack = 0;
4633a7c4 14
d667a7e6 15$VERSION = "1.1606";
9b0ceca9 16
f19ae7a7 17$ENV{HARNESS_ACTIVE} = 1;
18
9b0ceca9 19# Some experimental versions of OS/2 build have broken $?
20my $ignore_exitcode = $ENV{HARNESS_IGNORE_EXITCODE};
21
17a79f5b 22my $files_in_dir = $ENV{HARNESS_FILELEAK_IN_DIR};
23
9b0ceca9 24my $tests_skipped = 0;
25my $subtests_skipped = 0;
4633a7c4 26
c07a80fd 27@ISA=('Exporter');
cb1a09d0 28@EXPORT= qw(&runtests);
a0d0e21e 29@EXPORT_OK= qw($verbose $switches);
30
6c31b336 31$verbose = 0;
32$switches = "-w";
0a931e4a 33$columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
a0d0e21e 34
17a79f5b 35sub globdir { opendir DIRH, shift; my @f = readdir DIRH; closedir DIRH; @f }
36
a0d0e21e 37sub runtests {
38 my(@tests) = @_;
39 local($|) = 1;
0a931e4a 40 my($test,$te,$ok,$next,$max,$pct,$totbonus,@failed,%failedtests);
6c31b336 41 my $totmax = 0;
0a931e4a 42 my $totok = 0;
6c31b336 43 my $files = 0;
a0d0e21e 44 my $bad = 0;
45 my $good = 0;
46 my $total = @tests;
774d564b 47
48 # pass -I flags to children
81ff29e3 49 my $old5lib = $ENV{PERL5LIB};
774d564b 50
1250aba5 51 # VMS has a 255-byte limit on the length of %ENV entries, so
52 # toss the ones that involve perl_root, the install location
53 # for VMS
54 my $new5lib;
55 if ($^O eq 'VMS') {
56 $new5lib = join($Config{path_sep}, grep {!/perl_root/i;} @INC);
57 $switches =~ s/-(\S*[A-Z]\S*)/"-$1"/g;
58 }
59 else {
60 $new5lib = join($Config{path_sep}, @INC);
61 }
62
63 local($ENV{'PERL5LIB'}) = $new5lib;
a0d0e21e 64
17a79f5b 65 my @dir_files = globdir $files_in_dir if defined $files_in_dir;
a0d0e21e 66 my $t_start = new Benchmark;
67 while ($test = shift(@tests)) {
c07a80fd 68 $te = $test;
69 chop($te);
fe6f1558 70 if ($^O eq 'VMS') { $te =~ s/^.*\.t\./[.t./s; }
45c0de28 71 my $blank = (' ' x 77);
0d0c0d42 72 my $leader = "$te" . '.' x (20 - length($te));
73 my $ml = "";
23c4718a 74 $ml = "\r$blank\r$leader"
75 if -t STDOUT and not $ENV{HARNESS_NOTTY} and not $verbose;
0d0c0d42 76 print $leader;
6c31b336 77 my $fh = new FileHandle;
aa689395 78 $fh->open($test) or print "can't open $test. $!\n";
79 my $first = <$fh>;
80 my $s = $switches;
2b32313b 81 $s .= " $ENV{'HARNESS_PERL_SWITCHES'}"
82 if exists $ENV{'HARNESS_PERL_SWITCHES'};
da4582cd 83 $s .= join " ", q[ "-T"], map {qq["-I$_"]} @INC
84 if $first =~ /^#!.*\bperl.*-\w*T/;
aa689395 85 $fh->close or print "can't close $test. $!\n";
9636a016 86 my $cmd = ($ENV{'HARNESS_COMPILE_TEST'})
87 ? "./perl -I../lib ../utils/perlcc $test "
88 . "-run 2>> ./compilelog |"
89 : "$^X $s $test|";
a5077310 90 $cmd = "MCR $cmd" if $^O eq 'VMS';
aa689395 91 $fh->open($cmd) or print "can't run $test. $!\n";
c07a80fd 92 $ok = $next = $max = 0;
93 @failed = ();
7b13a3f5 94 my %todo = ();
95 my $bonus = 0;
fac76ed7 96 my $skipped = 0;
c854dc73 97 my $skip_reason;
c07a80fd 98 while (<$fh>) {
6c31b336 99 if( $verbose ){
c07a80fd 100 print $_;
101 }
7b13a3f5 102 if (/^1\.\.([0-9]+) todo([\d\s]+)\;/) {
103 $max = $1;
104 for (split(/\s+/, $2)) { $todo{$_} = 1; }
105 $totmax += $max;
106 $files++;
107 $next = 1;
45c0de28 108 } elsif (/^1\.\.([0-9]+)(\s*\#\s*[Ss]kip\S*(?>\s+)(.+))?/) {
c0ee6f5c 109 $max = $1;
110 $totmax += $max;
111 $files++;
112 $next = 1;
45c0de28 113 $skip_reason = $3 if not $max and defined $3;
c0ee6f5c 114 } elsif ($max && /^(not\s+)?ok\b/) {
115 my $this = $next;
116 if (/^not ok\s*(\d*)/){
117 $this = $1 if $1 > 0;
23c4718a 118 print "${ml}NOK $this" if $ml;
7b13a3f5 119 if (!$todo{$this}) {
120 push @failed, $this;
121 } else {
122 $ok++;
123 $totok++;
124 }
d2ab394d 125 } elsif (/^ok\s*(\d*) *(\s*\#\s*[Ss]kip\S*(?:(?>\s+)(.+))?)?$/) {
c0ee6f5c 126 $this = $1 if $1 > 0;
45c0de28 127 print "${ml}ok $this/$max" if $ml;
c0ee6f5c 128 $ok++;
129 $totok++;
fac76ed7 130 $skipped++ if defined $2;
c854dc73 131 my $reason;
132 $reason = 'unknown reason' if defined $2;
133 $reason = $3 if defined $3;
134 if (defined $reason and defined $skip_reason) {
135 # print "was: '$skip_reason' new '$reason'\n";
136 $skip_reason = 'various reasons'
137 if $skip_reason ne $reason;
138 } elsif (defined $reason) {
139 $skip_reason = $reason;
140 }
7b13a3f5 141 $bonus++, $totbonus++ if $todo{$this};
d2ab394d 142 } elsif (/^ok\s*(\d*)\s*\#([^\r]*)$/) {
143 $this = $1 if $1 > 0;
144 print "${ml}ok $this/$max" if $ml;
145 $ok++;
146 $totok++;
e1194749 147 } else {
d2ab394d 148 # an ok or not ok not matching the 3 cases above...
e1194749 149 # just ignore it for compatibility with TEST
150 next;
c07a80fd 151 }
c0ee6f5c 152 if ($this > $next) {
f767ed0d 153 # print "Test output counter mismatch [test $this]\n";
c0ee6f5c 154 # no need to warn probably
155 push @failed, $next..$this-1;
156 } elsif ($this < $next) {
157 #we have seen more "ok" lines than the number suggests
f767ed0d 158 print "Confused test output: test $this answered after test ", $next-1, "\n";
c0ee6f5c 159 $next = $this;
160 }
161 $next = $this + 1;
d667a7e6 162 } elsif (/^Bail out!\s*(.*)/i) { # magic words
163 die "FAILED--Further testing stopped" . ($1 ? ": $1\n" : ".\n");
164 }
c07a80fd 165 }
6c31b336 166 $fh->close; # must close to reap child resource values
9b0ceca9 167 my $wstatus = $ignore_exitcode ? 0 : $?; # Can trust $? ?
395b061e 168 my $estatus;
169 $estatus = ($^O eq 'VMS'
68dc0745 170 ? eval 'use vmsish "status"; $estatus = $?'
171 : $wstatus >> 8);
172 if ($wstatus) {
aa689395 173 my ($failed, $canon, $percent) = ('??', '??');
0d0c0d42 174 printf "${ml}dubious\n\tTest returned status $estatus (wstat %d, 0x%x)\n",
fb73857a 175 $wstatus,$wstatus;
68dc0745 176 print "\t\t(VMS status is $estatus)\n" if $^O eq 'VMS';
c0ee6f5c 177 if (corestatus($wstatus)) { # until we have a wait module
178 if ($have_devel_corestack) {
179 Devel::CoreStack::stack($^X);
180 } else {
181 print "\ttest program seems to have generated a core\n";
182 }
183 }
184 $bad++;
aa689395 185 if ($max) {
186 if ($next == $max + 1 and not @failed) {
187 print "\tafter all the subtests completed successfully\n";
188 $percent = 0;
189 $failed = 0; # But we do not set $canon!
190 } else {
191 push @failed, $next..$max;
192 $failed = @failed;
89d3b7e2 193 (my $txt, $canon) = canonfailed($max,$skipped,@failed);
aa689395 194 $percent = 100*(scalar @failed)/$max;
195 print "DIED. ",$txt;
196 }
197 }
198 $failedtests{$test} = { canon => $canon, max => $max || '??',
199 failed => $failed,
200 name => $test, percent => $percent,
760ac839 201 estat => $estatus, wstat => $wstatus,
202 };
c0ee6f5c 203 } elsif ($ok == $max && $next == $max+1) {
7b13a3f5 204 if ($max and $skipped + $bonus) {
205 my @msg;
45c0de28 206 push(@msg, "$skipped/$max skipped: $skip_reason")
7b13a3f5 207 if $skipped;
45c0de28 208 push(@msg, "$bonus/$max unexpectedly succeeded")
7b13a3f5 209 if $bonus;
45c0de28 210 print "${ml}ok, ".join(', ', @msg)."\n";
fac76ed7 211 } elsif ($max) {
45c0de28 212 print "${ml}ok\n";
213 } elsif (defined $skip_reason) {
214 print "skipped: $skip_reason\n";
215 $tests_skipped++;
c0ee6f5c 216 } else {
45c0de28 217 print "skipped test on this platform\n";
9b0ceca9 218 $tests_skipped++;
c0ee6f5c 219 }
c07a80fd 220 $good++;
6c31b336 221 } elsif ($max) {
222 if ($next <= $max) {
223 push @failed, $next..$max;
224 }
c07a80fd 225 if (@failed) {
89d3b7e2 226 my ($txt, $canon) = canonfailed($max,$skipped,@failed);
e9c9eb1f 227 print "${ml}$txt";
760ac839 228 $failedtests{$test} = { canon => $canon, max => $max,
229 failed => scalar @failed,
230 name => $test, percent => 100*(scalar @failed)/$max,
231 estat => '', wstat => '',
232 };
c07a80fd 233 } else {
c0ee6f5c 234 print "Don't know which tests failed: got $ok ok, expected $max\n";
760ac839 235 $failedtests{$test} = { canon => '??', max => $max,
236 failed => '??',
237 name => $test, percent => undef,
238 estat => '', wstat => '',
239 };
c07a80fd 240 }
241 $bad++;
6c31b336 242 } elsif ($next == 0) {
243 print "FAILED before any test output arrived\n";
244 $bad++;
760ac839 245 $failedtests{$test} = { canon => '??', max => '??',
246 failed => '??',
247 name => $test, percent => undef,
248 estat => '', wstat => '',
249 };
6c31b336 250 }
9b0ceca9 251 $subtests_skipped += $skipped;
17a79f5b 252 if (defined $files_in_dir) {
253 my @new_dir_files = globdir $files_in_dir;
254 if (@new_dir_files != @dir_files) {
255 my %f;
256 @f{@new_dir_files} = (1) x @new_dir_files;
257 delete @f{@dir_files};
258 my @f = sort keys %f;
259 print "LEAKED FILES: @f\n";
260 @dir_files = @new_dir_files;
261 }
262 }
a0d0e21e 263 }
264 my $t_total = timediff(new Benchmark, $t_start);
d667a7e6 265
774d564b 266 if ($^O eq 'VMS') {
267 if (defined $old5lib) {
268 $ENV{PERL5LIB} = $old5lib;
b876d4a6 269 } else {
774d564b 270 delete $ENV{PERL5LIB};
271 }
272 }
7b13a3f5 273 my $bonusmsg = '';
274 $bonusmsg = (" ($totbonus subtest".($totbonus>1?'s':'').
275 " UNEXPECTEDLY SUCCEEDED)")
276 if $totbonus;
9b0ceca9 277 if ($tests_skipped) {
c4f6c246 278 $bonusmsg .= ", $tests_skipped test" . ($tests_skipped != 1 ? 's' : '');
279 if ($subtests_skipped) {
280 $bonusmsg .= " and $subtests_skipped subtest"
281 . ($subtests_skipped != 1 ? 's' : '');
282 }
283 $bonusmsg .= ' skipped';
9b0ceca9 284 }
c4f6c246 285 elsif ($subtests_skipped) {
286 $bonusmsg .= ", $subtests_skipped subtest"
287 . ($subtests_skipped != 1 ? 's' : '')
288 . " skipped";
9b0ceca9 289 }
6c31b336 290 if ($bad == 0 && $totmax) {
7b13a3f5 291 print "All tests successful$bonusmsg.\n";
6c31b336 292 } elsif ($total==0){
293 die "FAILED--no tests were run for some reason.\n";
294 } elsif ($totmax==0) {
295 my $blurb = $total==1 ? "script" : "scripts";
c0ee6f5c 296 die "FAILED--$total test $blurb could be run, alas--no output ever seen\n";
c07a80fd 297 } else {
298 $pct = sprintf("%.2f", $good / $total * 100);
6c31b336 299 my $subpct = sprintf " %d/%d subtests failed, %.2f%% okay.",
300 $totmax - $totok, $totmax, 100*$totok/$totmax;
0a931e4a 301 # Create formats
302 # First, figure out max length of test names
303 my $failed_str = "Failed Test";
304 my $middle_str = " Status Wstat Total Fail Failed ";
305 my $list_str = "List of Failed";
306 my $max_namelen = length($failed_str);
760ac839 307 my $script;
0a931e4a 308 foreach $script (keys %failedtests) {
309 $max_namelen =
310 (length $failedtests{$script}->{name} > $max_namelen) ?
311 length $failedtests{$script}->{name} : $max_namelen;
312 }
313 my $list_len = $columns - length($middle_str) - $max_namelen;
314 if ($list_len < length($list_str)) {
315 $list_len = length($list_str);
316 $max_namelen = $columns - length($middle_str) - $list_len;
317 if ($max_namelen < length($failed_str)) {
318 $max_namelen = length($failed_str);
319 $columns = $max_namelen + length($middle_str) + $list_len;
320 }
321 }
322
323 my $fmt_top = "format STDOUT_TOP =\n"
324 . sprintf("%-${max_namelen}s", $failed_str)
325 . $middle_str
326 . $list_str . "\n"
327 . "-" x $columns
328 . "\n.\n";
329 my $fmt = "format STDOUT =\n"
330 . "@" . "<" x ($max_namelen - 1)
331 . " @>> @>>>> @>>>> @>>> ^##.##% "
332 . "^" . "<" x ($list_len - 1) . "\n"
333 . '{ $curtest->{name}, $curtest->{estat},'
334 . ' $curtest->{wstat}, $curtest->{max},'
335 . ' $curtest->{failed}, $curtest->{percent},'
336 . ' $curtest->{canon}'
337 . "\n}\n"
338 . "~~" . " " x ($columns - $list_len - 2) . "^"
339 . "<" x ($list_len - 1) . "\n"
340 . '$curtest->{canon}'
341 . "\n.\n";
342
343 eval $fmt_top;
344 die $@ if $@;
345 eval $fmt;
346 die $@ if $@;
347
348 # Now write to formats
760ac839 349 for $script (sort keys %failedtests) {
350 $curtest = $failedtests{$script};
351 write;
352 }
b876d4a6 353 if ($bad) {
9b0ceca9 354 $bonusmsg =~ s/^,\s*//;
355 print "$bonusmsg.\n" if $bonusmsg;
6c31b336 356 die "Failed $bad/$total test scripts, $pct% okay.$subpct\n";
c07a80fd 357 }
358 }
5603f27d 359 printf("Files=%d, Tests=%d, %s\n", $files, $totmax, timestr($t_total, 'nop'));
f0a9308e 360
361 return ($bad == 0 && $totmax) ;
c07a80fd 362}
363
aa689395 364my $tried_devel_corestack;
c0ee6f5c 365sub corestatus {
366 my($st) = @_;
c0ee6f5c 367
368 eval {require 'wait.ph'};
0dfaec25 369 my $ret = defined &WCOREDUMP ? WCOREDUMP($st) : $st & 0200;
c0ee6f5c 370
aa689395 371 eval { require Devel::CoreStack; $have_devel_corestack++ }
372 unless $tried_devel_corestack++;
c0ee6f5c 373
374 $ret;
375}
376
c07a80fd 377sub canonfailed ($@) {
89d3b7e2 378 my($max,$skipped,@failed) = @_;
6c31b336 379 my %seen;
380 @failed = sort {$a <=> $b} grep !$seen{$_}++, @failed;
c07a80fd 381 my $failed = @failed;
382 my @result = ();
383 my @canon = ();
384 my $min;
385 my $last = $min = shift @failed;
760ac839 386 my $canon;
c07a80fd 387 if (@failed) {
388 for (@failed, $failed[-1]) { # don't forget the last one
389 if ($_ > $last+1 || $_ == $last) {
390 if ($min == $last) {
391 push @canon, $last;
392 } else {
393 push @canon, "$min-$last";
394 }
395 $min = $_;
396 }
397 $last = $_;
398 }
399 local $" = ", ";
400 push @result, "FAILED tests @canon\n";
760ac839 401 $canon = "@canon";
a0d0e21e 402 } else {
c07a80fd 403 push @result, "FAILED test $last\n";
760ac839 404 $canon = $last;
a0d0e21e 405 }
c07a80fd 406
407 push @result, "\tFailed $failed/$max tests, ";
89d3b7e2 408 push @result, sprintf("%.2f",100*(1-$failed/$max)), "% okay";
409 my $ender = 's' x ($skipped > 1);
410 my $good = $max - $failed - $skipped;
411 my $goodper = sprintf("%.2f",100*($good/$max));
412 push @result, " (-$skipped skipped test$ender: $good okay, $goodper%)" if $skipped;
413 push @result, "\n";
760ac839 414 my $txt = join "", @result;
415 ($txt, $canon);
a0d0e21e 416}
417
4181;
cb1a09d0 419__END__
420
421=head1 NAME
422
423Test::Harness - run perl standard test scripts with statistics
424
425=head1 SYNOPSIS
426
427use Test::Harness;
428
429runtests(@tests);
430
431=head1 DESCRIPTION
432
7b13a3f5 433(By using the L<Test> module, you can write test scripts without
434knowing the exact output this module expects. However, if you need to
435know the specifics, read on!)
436
cb1a09d0 437Perl test scripts print to standard output C<"ok N"> for each single
438test, where C<N> is an increasing sequence of integers. The first line
c0ee6f5c 439output by a standard test script is C<"1..M"> with C<M> being the
cb1a09d0 440number of tests that should be run within the test
c0ee6f5c 441script. Test::Harness::runtests(@tests) runs all the testscripts
cb1a09d0 442named as arguments and checks standard output for the expected
443C<"ok N"> strings.
444
c0ee6f5c 445After all tests have been performed, runtests() prints some
cb1a09d0 446performance statistics that are computed by the Benchmark module.
447
6c31b336 448=head2 The test script output
449
450Any output from the testscript to standard error is ignored and
451bypassed, thus will be seen by the user. Lines written to standard
c0ee6f5c 452output containing C</^(not\s+)?ok\b/> are interpreted as feedback for
453runtests(). All other lines are discarded.
6c31b336 454
455It is tolerated if the test numbers after C<ok> are omitted. In this
456case Test::Harness maintains temporarily its own counter until the
457script supplies test numbers again. So the following test script
458
459 print <<END;
460 1..6
461 not ok
462 ok
463 not ok
464 ok
465 ok
466 END
467
d667a7e6 468will generate
6c31b336 469
470 FAILED tests 1, 3, 6
471 Failed 3/6 tests, 50.00% okay
472
473The global variable $Test::Harness::verbose is exportable and can be
c0ee6f5c 474used to let runtests() display the standard output of the script
6c31b336 475without altering the behavior otherwise.
476
fb73857a 477The global variable $Test::Harness::switches is exportable and can be
478used to set perl command line options used for running the test
479script(s). The default value is C<-w>.
480
fac76ed7 481If the standard output line contains substring C< # Skip> (with
482variations in spacing and case) after C<ok> or C<ok NUMBER>, it is
e1194749 483counted as a skipped test. In no other circumstance is anything
484allowed to follow C<ok> or C<ok NUMBER>. If the whole testscript
485succeeds, the count of skipped tests is included in the generated
486output.
487
488C<Test::Harness> reports the text after C< # Skip\S*\s+> as a reason
489for skipping. Similarly, one can include a similar explanation in a
490C<1..0> line emitted if the test is skipped completely:
45c0de28 491
492 1..0 # Skipped: no leverage found
493
d667a7e6 494As an emergency measure, a test script can decide that further tests
495are useless (e.g. missing dependencies) and testing should stop
496immediately. In that case the test script prints the magic words
497
498 Bail out!
499
500to standard output. Any message after these words will be displayed by
501C<Test::Harness> as the reason why testing is stopped.
502
cb1a09d0 503=head1 EXPORT
504
c0ee6f5c 505C<&runtests> is exported by Test::Harness per default.
cb1a09d0 506
507=head1 DIAGNOSTICS
508
509=over 4
510
511=item C<All tests successful.\nFiles=%d, Tests=%d, %s>
512
513If all tests are successful some statistics about the performance are
514printed.
515
6c31b336 516=item C<FAILED tests %s\n\tFailed %d/%d tests, %.2f%% okay.>
517
518For any single script that has failing subtests statistics like the
519above are printed.
520
521=item C<Test returned status %d (wstat %d)>
522
81ff29e3 523Scripts that return a non-zero exit status, both C<$? E<gt>E<gt> 8> and C<$?> are
6c31b336 524printed in a message similar to the above.
525
526=item C<Failed 1 test, %.2f%% okay. %s>
cb1a09d0 527
6c31b336 528=item C<Failed %d/%d tests, %.2f%% okay. %s>
cb1a09d0 529
530If not all tests were successful, the script dies with one of the
531above messages.
532
d667a7e6 533=item C<FAILED--Further testing stopped%s>
534
535If a single subtest decides that further testing will not make sense,
536the script dies with this message.
537
cb1a09d0 538=back
539
9b0ceca9 540=head1 ENVIRONMENT
541
17a79f5b 542Setting C<HARNESS_IGNORE_EXITCODE> makes harness ignore the exit status
9b0ceca9 543of child processes.
544
0d0c0d42 545Setting C<HARNESS_NOTTY> to a true value forces it to behave as though
546STDOUT were not a console. You may need to set this if you don't want
547harness to output more frequent progress messages using carriage returns.
548Some consoles may not handle carriage returns properly (which results
549in a somewhat messy output).
550
9636a016 551Setting C<HARNESS_COMPILE_TEST> to a true value will make harness attempt
552to compile the test using C<perlcc> before running it.
553
17a79f5b 554If C<HARNESS_FILELEAK_IN_DIR> is set to the name of a directory, harness
555will check after each test whether new files appeared in that directory,
556and report them as
557
558 LEAKED FILES: scr.tmp 0 my.db
559
560If relative, directory name is with respect to the current directory at
561the moment runtests() was called. Putting absolute path into
562C<HARNESS_FILELEAK_IN_DIR> may give more predicatable results.
563
2b32313b 564The value of C<HARNESS_PERL_SWITCHES> will be prepended to the
565switches used to invoke perl on each test. For example, setting
566C<HARNESS_PERL_SWITCHES> to "-W" will run all tests with all
567warnings enabled.
568
0a931e4a 569If C<HARNESS_COLUMNS> is set, then this value will be used for the
570width of the terminal. If it is not set then it will default to
571C<COLUMNS>. If this is not set, it will default to 80. Note that users
572of Bourne-sh based shells will need to C<export COLUMNS> for this
573module to use that variable.
574
f19ae7a7 575Harness sets C<HARNESS_ACTIVE> before executing the individual tests.
576This allows the tests to determine if they are being executed through the
577harness or by any other means.
578
cb1a09d0 579=head1 SEE ALSO
580
7b13a3f5 581L<Test> for writing test scripts and also L<Benchmark> for the
582underlying timing routines.
c07a80fd 583
584=head1 AUTHORS
585
586Either Tim Bunce or Andreas Koenig, we don't know. What we know for
587sure is, that it was inspired by Larry Wall's TEST script that came
b876d4a6 588with perl distributions for ages. Numerous anonymous contributors
589exist. Current maintainer is Andreas Koenig.
cb1a09d0 590
591=head1 BUGS
592
593Test::Harness uses $^X to determine the perl binary to run the tests
6c31b336 594with. Test scripts running via the shebang (C<#!>) line may not be
595portable because $^X is not consistent for shebang scripts across
cb1a09d0 596platforms. This is no problem when Test::Harness is run with an
6c31b336 597absolute path to the perl binary or when $^X can be found in the path.
cb1a09d0 598
599=cut