1package Test::Harness; 2 3require 5.00405; 4 5use strict; 6 7use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ ); 8use constant IS_VMS => ( $^O eq 'VMS' ); 9 10use TAP::Harness (); 11use TAP::Parser::Aggregator (); 12use TAP::Parser::Source::Perl (); 13 14use TAP::Parser::Utils qw( split_shell ); 15 16use Config; 17use Exporter; 18 19# TODO: Emulate at least some of these 20use vars qw( 21 $VERSION 22 @ISA @EXPORT @EXPORT_OK 23 $Verbose $Switches $Debug 24 $verbose $switches $debug 25 $Columns 26 $Color 27 $Directives 28 $Timer 29 $Strap 30 $has_time_hires 31 $IgnoreExit 32); 33 34# $ML $Last_ML_Print 35 36BEGIN { 37 eval q{use Time::HiRes 'time'}; 38 $has_time_hires = !$@; 39} 40 41=head1 NAME 42 43Test::Harness - Run Perl standard test scripts with statistics 44 45=head1 VERSION 46 47Version 3.17 48 49=cut 50 51$VERSION = '3.17'; 52 53# Backwards compatibility for exportable variable names. 54*verbose = *Verbose; 55*switches = *Switches; 56*debug = *Debug; 57 58$ENV{HARNESS_ACTIVE} = 1; 59$ENV{HARNESS_VERSION} = $VERSION; 60 61END { 62 63 # For VMS. 64 delete $ENV{HARNESS_ACTIVE}; 65 delete $ENV{HARNESS_VERSION}; 66} 67 68@ISA = ('Exporter'); 69@EXPORT = qw(&runtests); 70@EXPORT_OK = qw(&execute_tests $verbose $switches); 71 72$Verbose = $ENV{HARNESS_VERBOSE} || 0; 73$Debug = $ENV{HARNESS_DEBUG} || 0; 74$Switches = '-w'; 75$Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80; 76$Columns--; # Some shells have trouble with a full line of text. 77$Timer = $ENV{HARNESS_TIMER} || 0; 78$Color = $ENV{HARNESS_COLOR} || 0; 79$IgnoreExit = $ENV{HARNESS_IGNORE_EXIT} || 0; 80 81=head1 SYNOPSIS 82 83 use Test::Harness; 84 85 runtests(@test_files); 86 87=head1 DESCRIPTION 88 89Although, for historical reasons, the L<Test::Harness> distribution 90takes its name from this module it now exists only to provide 91L<TAP::Harness> with an interface that is somewhat backwards compatible 92with L<Test::Harness> 2.xx. If you're writing new code consider using 93L<TAP::Harness> directly instead. 94 95Emulation is provided for C<runtests> and C<execute_tests> but the 96pluggable 'Straps' interface that previous versions of L<Test::Harness> 97supported is not reproduced here. Straps is now available as a stand 98alone module: L<Test::Harness::Straps>. 99 100See L<TAP::Parser>, L<TAP::Harness> for the main documentation for this 101distribution. 102 103=head1 FUNCTIONS 104 105The following functions are available. 106 107=head2 runtests( @test_files ) 108 109This runs all the given I<@test_files> and divines whether they passed 110or failed based on their output to STDOUT (details above). It prints 111out each individual test which failed along with a summary report and 112a how long it all took. 113 114It returns true if everything was ok. Otherwise it will C<die()> with 115one of the messages in the DIAGNOSTICS section. 116 117=cut 118 119sub _has_taint { 120 my $test = shift; 121 return TAP::Parser::Source::Perl->get_taint( 122 TAP::Parser::Source::Perl->shebang($test) ); 123} 124 125sub _aggregate { 126 my ( $harness, $aggregate, @tests ) = @_; 127 128 # Don't propagate to our children 129 local $ENV{HARNESS_OPTIONS}; 130 131 _apply_extra_INC($harness); 132 _aggregate_tests( $harness, $aggregate, @tests ); 133} 134 135# Make sure the child seens all the extra junk in @INC 136sub _apply_extra_INC { 137 my $harness = shift; 138 139 $harness->callback( 140 parser_args => sub { 141 my ( $args, $test ) = @_; 142 push @{ $args->{switches} }, map {"-I$_"} _filtered_inc(); 143 } 144 ); 145} 146 147sub _aggregate_tests { 148 my ( $harness, $aggregate, @tests ) = @_; 149 $aggregate->start(); 150 $harness->aggregate_tests( $aggregate, @tests ); 151 $aggregate->stop(); 152 153} 154 155sub runtests { 156 my @tests = @_; 157 158 # shield against -l 159 local ( $\, $, ); 160 161 my $harness = _new_harness(); 162 my $aggregate = TAP::Parser::Aggregator->new(); 163 164 _aggregate( $harness, $aggregate, @tests ); 165 166 $harness->formatter->summary($aggregate); 167 168 my $total = $aggregate->total; 169 my $passed = $aggregate->passed; 170 my $failed = $aggregate->failed; 171 172 my @parsers = $aggregate->parsers; 173 174 my $num_bad = 0; 175 for my $parser (@parsers) { 176 $num_bad++ if $parser->has_problems; 177 } 178 179 die(sprintf( 180 "Failed %d/%d test programs. %d/%d subtests failed.\n", 181 $num_bad, scalar @parsers, $failed, $total 182 ) 183 ) if $num_bad; 184 185 return $total && $total == $passed; 186} 187 188sub _canon { 189 my @list = sort { $a <=> $b } @_; 190 my @ranges = (); 191 my $count = scalar @list; 192 my $pos = 0; 193 194 while ( $pos < $count ) { 195 my $end = $pos + 1; 196 $end++ while $end < $count && $list[$end] <= $list[ $end - 1 ] + 1; 197 push @ranges, ( $end == $pos + 1 ) 198 ? $list[$pos] 199 : join( '-', $list[$pos], $list[ $end - 1 ] ); 200 $pos = $end; 201 } 202 203 return join( ' ', @ranges ); 204} 205 206sub _new_harness { 207 my $sub_args = shift || {}; 208 209 my ( @lib, @switches ); 210 my @opt = split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} ); 211 while ( my $opt = shift @opt ) { 212 if ( $opt =~ /^ -I (.*) $ /x ) { 213 push @lib, length($1) ? $1 : shift @opt; 214 } 215 else { 216 push @switches, $opt; 217 } 218 } 219 220 # Do things the old way on VMS... 221 push @lib, _filtered_inc() if IS_VMS; 222 223 # If $Verbose isn't numeric default to 1. This helps core. 224 my $verbosity = ( $Verbose ? ( $Verbose !~ /\d/ ) ? 1 : $Verbose : 0 ); 225 226 my $args = { 227 timer => $Timer, 228 directives => $Directives, 229 lib => \@lib, 230 switches => \@switches, 231 color => $Color, 232 verbosity => $verbosity, 233 ignore_exit => $IgnoreExit, 234 }; 235 236 $args->{stdout} = $sub_args->{out} 237 if exists $sub_args->{out}; 238 239 if ( defined( my $env_opt = $ENV{HARNESS_OPTIONS} ) ) { 240 for my $opt ( split /:/, $env_opt ) { 241 if ( $opt =~ /^j(\d*)$/ ) { 242 $args->{jobs} = $1 || 9; 243 } 244 elsif ( $opt eq 'c' ) { 245 $args->{color} = 1; 246 } 247 else { 248 die "Unknown HARNESS_OPTIONS item: $opt\n"; 249 } 250 } 251 } 252 253 return TAP::Harness->new($args); 254} 255 256# Get the parts of @INC which are changed from the stock list AND 257# preserve reordering of stock directories. 258sub _filtered_inc { 259 my @inc = grep { !ref } @INC; #28567 260 261 if (IS_VMS) { 262 263 # VMS has a 255-byte limit on the length of %ENV entries, so 264 # toss the ones that involve perl_root, the install location 265 @inc = grep !/perl_root/i, @inc; 266 267 } 268 elsif (IS_WIN32) { 269 270 # Lose any trailing backslashes in the Win32 paths 271 s/[\\\/]+$// foreach @inc; 272 } 273 274 my @default_inc = _default_inc(); 275 276 my @new_inc; 277 my %seen; 278 for my $dir (@inc) { 279 next if $seen{$dir}++; 280 281 if ( $dir eq ( $default_inc[0] || '' ) ) { 282 shift @default_inc; 283 } 284 else { 285 push @new_inc, $dir; 286 } 287 288 shift @default_inc while @default_inc and $seen{ $default_inc[0] }; 289 } 290 291 return @new_inc; 292} 293 294{ 295 296 # Cache this to avoid repeatedly shelling out to Perl. 297 my @inc; 298 299 sub _default_inc { 300 return @inc if @inc; 301 302 local $ENV{PERL5LIB}; 303 local $ENV{PERLLIB}; 304 305 my $perl = $ENV{HARNESS_PERL} || $^X; 306 307 # Avoid using -l for the benefit of Perl 6 308 chomp( @inc = `$perl -e "print join qq[\\n], \@INC, q[]"` ); 309 return @inc; 310 } 311} 312 313sub _check_sequence { 314 my @list = @_; 315 my $prev; 316 while ( my $next = shift @list ) { 317 return if defined $prev && $next <= $prev; 318 $prev = $next; 319 } 320 321 return 1; 322} 323 324sub execute_tests { 325 my %args = @_; 326 327 my $harness = _new_harness( \%args ); 328 my $aggregate = TAP::Parser::Aggregator->new(); 329 330 my %tot = ( 331 bonus => 0, 332 max => 0, 333 ok => 0, 334 bad => 0, 335 good => 0, 336 files => 0, 337 tests => 0, 338 sub_skipped => 0, 339 todo => 0, 340 skipped => 0, 341 bench => undef, 342 ); 343 344 # Install a callback so we get to see any plans the 345 # harness executes. 346 $harness->callback( 347 made_parser => sub { 348 my $parser = shift; 349 $parser->callback( 350 plan => sub { 351 my $plan = shift; 352 if ( $plan->directive eq 'SKIP' ) { 353 $tot{skipped}++; 354 } 355 } 356 ); 357 } 358 ); 359 360 _aggregate( $harness, $aggregate, @{ $args{tests} } ); 361 362 $tot{bench} = $aggregate->elapsed; 363 my @tests = $aggregate->descriptions; 364 365 # TODO: Work out the circumstances under which the files 366 # and tests totals can differ. 367 $tot{files} = $tot{tests} = scalar @tests; 368 369 my %failedtests = (); 370 my %todo_passed = (); 371 372 for my $test (@tests) { 373 my ($parser) = $aggregate->parsers($test); 374 375 my @failed = $parser->failed; 376 377 my $wstat = $parser->wait; 378 my $estat = $parser->exit; 379 my $planned = $parser->tests_planned; 380 my @errors = $parser->parse_errors; 381 my $passed = $parser->passed; 382 my $actual_passed = $parser->actual_passed; 383 384 my $ok_seq = _check_sequence( $parser->actual_passed ); 385 386 # Duplicate exit, wait status semantics of old version 387 $estat ||= '' unless $wstat; 388 $wstat ||= ''; 389 390 $tot{max} += ( $planned || 0 ); 391 $tot{bonus} += $parser->todo_passed; 392 $tot{ok} += $passed > $actual_passed ? $passed : $actual_passed; 393 $tot{sub_skipped} += $parser->skipped; 394 $tot{todo} += $parser->todo; 395 396 if ( @failed || $estat || @errors ) { 397 $tot{bad}++; 398 399 my $huh_planned = $planned ? undef : '??'; 400 my $huh_errors = $ok_seq ? undef : '??'; 401 402 $failedtests{$test} = { 403 'canon' => $huh_planned 404 || $huh_errors 405 || _canon(@failed) 406 || '??', 407 'estat' => $estat, 408 'failed' => $huh_planned 409 || $huh_errors 410 || scalar @failed, 411 'max' => $huh_planned || $planned, 412 'name' => $test, 413 'wstat' => $wstat 414 }; 415 } 416 else { 417 $tot{good}++; 418 } 419 420 my @todo = $parser->todo_passed; 421 if (@todo) { 422 $todo_passed{$test} = { 423 'canon' => _canon(@todo), 424 'estat' => $estat, 425 'failed' => scalar @todo, 426 'max' => scalar $parser->todo, 427 'name' => $test, 428 'wstat' => $wstat 429 }; 430 } 431 } 432 433 return ( \%tot, \%failedtests, \%todo_passed ); 434} 435 436=head2 execute_tests( tests => \@test_files, out => \*FH ) 437 438Runs all the given C<@test_files> (just like C<runtests()>) but 439doesn't generate the final report. During testing, progress 440information will be written to the currently selected output 441filehandle (usually C<STDOUT>), or to the filehandle given by the 442C<out> parameter. The I<out> is optional. 443 444Returns a list of two values, C<$total> and C<$failed>, describing the 445results. C<$total> is a hash ref summary of all the tests run. Its 446keys and values are this: 447 448 bonus Number of individual todo tests unexpectedly passed 449 max Number of individual tests ran 450 ok Number of individual tests passed 451 sub_skipped Number of individual tests skipped 452 todo Number of individual todo tests 453 454 files Number of test files ran 455 good Number of test files passed 456 bad Number of test files failed 457 tests Number of test files originally given 458 skipped Number of test files skipped 459 460If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've 461got a successful test. 462 463C<$failed> is a hash ref of all the test scripts that failed. Each key 464is the name of a test script, each value is another hash representing 465how that script failed. Its keys are these: 466 467 name Name of the test which failed 468 estat Script's exit value 469 wstat Script's wait status 470 max Number of individual tests 471 failed Number which failed 472 canon List of tests which failed (as string). 473 474C<$failed> should be empty if everything passed. 475 476=cut 477 4781; 479__END__ 480 481=head1 EXPORT 482 483C<&runtests> is exported by C<Test::Harness> by default. 484 485C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are 486exported upon request. 487 488=head1 ENVIRONMENT VARIABLES THAT TAP::HARNESS::COMPATIBLE SETS 489 490C<Test::Harness> sets these before executing the individual tests. 491 492=over 4 493 494=item C<HARNESS_ACTIVE> 495 496This is set to a true value. It allows the tests to determine if they 497are being executed through the harness or by any other means. 498 499=item C<HARNESS_VERSION> 500 501This is the version of C<Test::Harness>. 502 503=back 504 505=head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS 506 507=over 4 508 509=item C<HARNESS_TIMER> 510 511Setting this to true will make the harness display the number of 512milliseconds each test took. You can also use F<prove>'s C<--timer> 513switch. 514 515=item C<HARNESS_VERBOSE> 516 517If true, C<Test::Harness> will output the verbose results of running 518its tests. Setting C<$Test::Harness::verbose> will override this, 519or you can use the C<-v> switch in the F<prove> utility. 520 521=item C<HARNESS_OPTIONS> 522 523Provide additional options to the harness. Currently supported options are: 524 525=over 526 527=item C<< j<n> >> 528 529Run <n> (default 9) parallel jobs. 530 531=item C<< f >> 532 533Use forked parallelism. 534 535=back 536 537Multiple options may be separated by colons: 538 539 HARNESS_OPTIONS=j9:f make test 540 541=back 542 543=head1 Taint Mode 544 545Normally when a Perl program is run in taint mode the contents of the 546C<PERL5LIB> environment variable do not appear in C<@INC>. 547 548Because C<PERL5LIB> is often used during testing to add build 549directories to C<@INC> C<Test::Harness> (actually 550L<TAP::Parser::Source::Perl>) passes the names of any directories found 551in C<PERL5LIB> as -I switches. The net effect of this is that 552C<PERL5LIB> is honoured even in taint mode. 553 554=head1 SEE ALSO 555 556L<TAP::Harness> 557 558=head1 BUGS 559 560Please report any bugs or feature requests to 561C<bug-test-harness at rt.cpan.org>, or through the web interface at 562L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>. I will be 563notified, and then you'll automatically be notified of progress on your bug 564as I make changes. 565 566=head1 AUTHORS 567 568Andy Armstrong C<< <andy@hexten.net> >> 569 570L<Test::Harness> 2.64 (maintained by Andy Lester and on which this 571module is based) has this attribution: 572 573 Either Tim Bunce or Andreas Koenig, we don't know. What we know for 574 sure is, that it was inspired by Larry Wall's F<TEST> script that came 575 with perl distributions for ages. Numerous anonymous contributors 576 exist. Andreas Koenig held the torch for many years, and then 577 Michael G Schwern. 578 579=head1 LICENCE AND COPYRIGHT 580 581Copyright (c) 2007-2008, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved. 582 583This module is free software; you can redistribute it and/or 584modify it under the same terms as Perl itself. See L<perlartistic>. 585 586