12 use TAP::Parser::Aggregator;
13 use TAP::Parser::Multiplexer;
15 use vars qw($VERSION @ISA);
21 TAP::Harness - Run test scripts with statistics
31 $ENV{HARNESS_ACTIVE} = 1;
32 $ENV{HARNESS_VERSION} = $VERSION;
37 delete $ENV{HARNESS_ACTIVE};
38 delete $ENV{HARNESS_VERSION};
43 This is a simple test harness which allows tests to be run and results
44 automatically aggregated and output to STDOUT.
49 my $harness = TAP::Harness->new( \%args );
50 $harness->runtests(@tests);
59 return $self->{error} unless @_;
60 $self->{error} = shift;
66 directives verbosity timer failures errors stdout color
71 my ( $self, $libs ) = @_;
72 $libs = [$libs] unless 'ARRAY' eq ref $libs;
74 return [ map {"-I$_"} @$libs ];
76 switches => sub { shift; shift },
77 exec => sub { shift; shift },
78 merge => sub { shift; shift },
79 formatter_class => sub { shift; shift },
80 formatter => sub { shift; shift },
81 jobs => sub { shift; shift },
82 fork => sub { shift; shift },
83 test_args => sub { shift; shift },
86 for my $method ( sort keys %VALIDATION_FOR ) {
88 if ( $method eq 'lib' || $method eq 'switches' ) {
92 $self->{$method} ||= [];
94 ? @{ $self->{$method} }
97 $self->_croak("Too many arguments to method '$method'")
100 $args = [$args] unless ref $args;
101 $self->{$method} = $args;
108 return $self->{$method} unless @_;
109 $self->{$method} = shift;
114 for my $method (@FORMATTER_ARGS) {
118 return $self->formatter->$method(@_);
123 ##############################################################################
133 lib => [ 'lib', 'blib/lib' ],
135 my $harness = TAP::Harness->new( \%args );
137 The constructor returns a new C<TAP::Harness> object. It accepts an optional
138 hashref whose allowed keys are:
144 Set the verbosity level:
146 1 verbose Print individual test results to STDOUT.
148 -1 quiet Suppress some test output (mostly failures
149 while tests are running).
150 -2 really quiet Suppress everything but the tests summary.
154 Append run time for each test to output. Uses L<Time::HiRes> if available.
158 Only show test failures (this is a no-op if C<verbose> is selected).
162 Accepts a scalar value or array ref of scalar values indicating which paths to
163 allowed libraries should be included if Perl tests are executed. Naturally,
164 this only makes sense in the context of tests written in Perl.
168 Accepts a scalar value or array ref of scalar values indicating which switches
169 should be included if Perl tests are executed. Naturally, this only makes
170 sense in the context of tests written in Perl.
174 A reference to an C<@INC> style array of arguments to be passed to each
179 Attempt to produce color output.
183 Typically, Perl tests are run through this. However, anything which spits out
184 TAP is fine. You can use this argument to specify the name of the program
185 (and optional switches) to run your tests with:
187 exec => ['/usr/bin/ruby', '-w']
191 If C<merge> is true the harness will create parsers that merge STDOUT
192 and STDERR together for any processes they start.
194 =item * C<formatter_class>
196 The name of the class to use to format output. The default is
197 L<TAP::Formatter::Console>.
201 If set C<formatter> must be an object that is capable of formatting the
202 TAP output. See L<TAP::Formatter::Console> for an example.
206 If parse errors are found in the TAP output, a note of this will be made
207 in the summary report. To see all of the parse errors, set this argument to
212 =item * C<directives>
214 If set to a true value, only test results with directives will be displayed.
215 This overrides other settings such as C<verbose> or C<failures>.
219 A filehandle for catching standard output.
223 Any keys for which the value is C<undef> will be ignored.
227 # new supplied by TAP::Base
230 my @legal_callback = qw(
239 my ( $self, $arg_for ) = @_;
242 $self->SUPER::_initialize( $arg_for, \@legal_callback );
243 my %arg_for = %$arg_for; # force a shallow copy
245 for my $name ( sort keys %VALIDATION_FOR ) {
246 my $property = delete $arg_for{$name};
247 if ( defined $property ) {
248 my $validate = $VALIDATION_FOR{$name};
250 my $value = $self->$validate($property);
251 if ( $self->_error ) {
254 $self->$name($value);
258 $self->jobs(1) unless defined $self->jobs;
260 unless ( $self->formatter ) {
262 $self->formatter_class( my $class = $self->formatter_class
263 || 'TAP::Formatter::Console' );
265 croak "Bad module name $class"
266 unless $class =~ /^ \w+ (?: :: \w+ ) *$/x;
268 eval "require $class";
269 $self->_croak("Can't load $class") if $@;
271 # This is a little bodge to preserve legacy behaviour. It's
272 # pretty horrible that we know which args are destined for
274 my %formatter_args = ( jobs => $self->jobs );
275 for my $name (@FORMATTER_ARGS) {
276 if ( defined( my $property = delete $arg_for{$name} ) ) {
277 $formatter_args{$name} = $property;
281 $self->formatter( $class->new( \%formatter_args ) );
284 if ( my @props = sort keys %arg_for ) {
285 $self->_croak("Unknown arguments to TAP::Harness::new (@props)");
292 ##############################################################################
294 =head2 Instance Methods
298 $harness->runtests(@tests);
300 Accepts and array of C<@tests> to be run. This should generally be the names
301 of test files, but this is not required. Each element in C<@tests> will be
302 passed to C<TAP::Parser::new()> as a C<source>. See L<TAP::Parser> for more
305 It is possible to provide aliases that will be displayed in place of the
306 test name by supplying the test as a reference to an array containing
307 C<< [ $test, $alias ] >>:
309 $harness->runtests( [ 't/foo.t', 'Foo Once' ],
310 [ 't/foo.t', 'Foo Twice' ] );
312 Normally it is an error to attempt to run the same test twice. Aliases
313 allow you to overcome this limitation by giving each run of the test a
316 Tests will be run in the order found.
318 If the environment variable C<PERL_TEST_HARNESS_DUMP_TAP> is defined it
319 should name a directory into which a copy of the raw TAP for each test
320 will be written. TAP is written to files named for each test.
321 Subdirectories will be created as needed.
323 Returns a L<TAP::Parser::Aggregator> containing the test results.
328 my ( $self, @tests ) = @_;
330 my $aggregate = TAP::Parser::Aggregator->new;
332 $self->_make_callback( 'before_runtests', $aggregate );
334 $self->aggregate_tests( $aggregate, @tests );
336 $self->formatter->summary($aggregate);
337 $self->_make_callback( 'after_runtests', $aggregate );
343 my ( $self, $aggregate, $test, $parser ) = @_;
345 $self->_make_callback( 'after_test', $test, $parser );
346 $aggregate->add( $test->[1], $parser );
349 sub _aggregate_forked {
350 my ( $self, $aggregate, @tests ) = @_;
352 eval { require Parallel::Iterator };
354 croak "Parallel::Iterator required for --fork option ($@)"
357 my $iter = Parallel::Iterator::iterate(
358 { workers => $self->jobs || 0 },
360 my ( $id, $test ) = @_;
362 my ( $parser, $session ) = $self->make_parser($test);
364 while ( defined( my $result = $parser->next ) ) {
365 exit 1 if $result->is_bailout;
368 $self->finish_parser( $parser, $session );
370 # Can't serialise coderefs...
371 delete $parser->{_iter};
372 delete $parser->{_stream};
373 delete $parser->{_grammar};
379 while ( my ( $id, $parser ) = $iter->() ) {
380 $self->_after_test( $aggregate, $tests[$id], $parser );
386 sub _aggregate_parallel {
387 my ( $self, $aggregate, @tests ) = @_;
389 my $jobs = $self->jobs;
390 my $mux = TAP::Parser::Multiplexer->new;
394 # Keep multiplexer topped up
395 while ( @tests && $mux->parsers < $jobs ) {
396 my $test = shift @tests;
397 my ( $parser, $session ) = $self->make_parser($test);
398 $mux->add( $parser, [ $session, $test ] );
401 if ( my ( $parser, $stash, $result ) = $mux->next ) {
402 my ( $session, $test ) = @$stash;
403 if ( defined $result ) {
404 $session->result($result);
405 exit 1 if $result->is_bailout;
409 # End of parser. Automatically removed from the mux.
410 $self->finish_parser( $parser, $session );
411 $self->_after_test( $aggregate, $test, $parser );
420 sub _aggregate_single {
421 my ( $self, $aggregate, @tests ) = @_;
423 for my $test (@tests) {
424 my ( $parser, $session ) = $self->make_parser($test);
426 while ( defined( my $result = $parser->next ) ) {
427 $session->result($result);
428 if ( $result->is_bailout ) {
430 # Keep reading until input is exhausted in the hope
431 # of allowing any pending diagnostics to show up.
432 1 while $parser->next;
437 $self->finish_parser( $parser, $session );
438 $self->_after_test( $aggregate, $test, $parser );
444 =head3 C<aggregate_tests>
446 $harness->aggregate_tests( $aggregate, @tests );
448 Run the named tests and display a summary of result. Tests will be run
451 Test results will be added to the supplied L<TAP::Parser::Aggregator>.
452 C<aggregate_tests> may be called multiple times to run several sets of
453 tests. Multiple C<Test::Harness> instances may be used to pass results
454 to a single aggregator so that different parts of a complex test suite
455 may be run using different C<TAP::Harness> settings. This is useful, for
456 example, in the case where some tests should run in parallel but others
457 are unsuitable for parallel execution.
459 my $formatter = TAP::Formatter::Console->new;
460 my $ser_harness = TAP::Harness->new( { formatter => $formatter } );
461 my $par_harness = TAP::Harness->new( { formatter => $formatter,
463 my $aggregator = TAP::Parser::Aggregator->new;
465 $aggregator->start();
466 $ser_harness->aggregate_tests( $aggregator, @ser_tests );
467 $par_harness->aggregate_tests( $aggregator, @par_tests );
469 $formatter->summary( $aggregator );
471 Note that for simpler testing requirements it will often be possible to
472 replace the above code with a single call to C<runtests>.
474 Each elements of the @tests array is either
478 =item * the file name of a test script to run
480 =item * a reference to a [ file name, display name ]
484 When you supply a separate display name it becomes possible to run a
485 test more than once; the display name is effectively the alias by which
486 the test is known inside the harness. The harness doesn't care if it
487 runs the same script more than once when each invocation uses a
492 sub aggregate_tests {
493 my ( $self, $aggregate, @tests ) = @_;
495 my $jobs = $self->jobs;
497 my @expanded = map { 'ARRAY' eq ref $_ ? $_ : [ $_, $_ ] } @tests;
500 local $ENV{HARNESS_IS_VERBOSE} = 1
501 if $self->formatter->verbosity > 0;
503 # Formatter gets only names
504 $self->formatter->prepare( map { $_->[1] } @expanded );
506 if ( $self->jobs > 1 ) {
508 $self->_aggregate_forked( $aggregate, @expanded );
511 $self->_aggregate_parallel( $aggregate, @expanded );
515 $self->_aggregate_single( $aggregate, @expanded );
523 Returns the number of concurrent test runs the harness is handling. For the default
524 harness this value is always 1. A parallel harness such as L<TAP::Harness::Parallel>
525 will override this to return the number of jobs it is handling.
529 If true the harness will attempt to fork and run the parser for each
530 test in a separate process. Currently this option requires
531 L<Parallel::Iterator> to be installed.
535 ##############################################################################
539 C<TAP::Harness> is designed to be (mostly) easy to subclass. If you don't
540 like how a particular feature functions, just override the desired methods.
544 TODO: This is out of date
546 The following methods are ones you may wish to override if you want to
547 subclass C<TAP::Harness>.
551 $harness->summary( \%args );
553 C<summary> prints the summary report after all tests are run. The argument is
554 a hashref with the following keys:
560 This is created with C<< Benchmark->new >> and it the time the tests started.
561 You can print a useful summary time, if desired, with:
563 $self->output(timestr( timediff( Benchmark->new, $start_time ), 'nop' ));
567 This is an array reference of all test names. To get the L<TAP::Parser>
568 object for individual tests:
570 my $aggregate = $args->{aggregate};
571 my $tests = $args->{tests};
573 for my $name ( @$tests ) {
574 my ($parser) = $aggregate->parsers($test);
575 ... do something with $parser
578 This is a bit clunky and will be cleaned up in a later release.
584 sub _get_parser_args {
585 my ( $self, $test ) = @_;
586 my $test_prog = $test->[0];
589 @switches = $self->lib if $self->lib;
590 push @switches => $self->switches if $self->switches;
591 $args{switches} = \@switches;
592 $args{spool} = $self->_open_spool($test_prog);
593 $args{merge} = $self->merge;
594 $args{exec} = $self->exec;
596 if ( my $exec = $self->exec ) {
597 $args{exec} = [ @$exec, $test_prog ];
600 $args{source} = $test_prog;
603 if ( defined( my $test_args = $self->test_args ) ) {
604 $args{test_args} = $test_args;
610 =head3 C<make_parser>
612 Make a new parser and display formatter session. Typically used and/or
613 overridden in subclasses.
615 my ( $parser, $session ) = $harness->make_parser;
621 my ( $self, $test ) = @_;
623 my $args = $self->_get_parser_args($test);
624 $self->_make_callback( 'parser_args', $args, $test );
625 my $parser = TAP::Parser->new($args);
627 $self->_make_callback( 'made_parser', $parser, $test );
628 my $session = $self->formatter->open_test( $test->[1], $parser );
630 return ( $parser, $session );
633 =head3 C<finish_parser>
635 Terminate use of a parser. Typically used and/or overridden in
636 subclasses. The parser isn't destroyed as a result of this.
641 my ( $self, $parser, $session ) = @_;
643 $session->close_test;
644 $self->_close_spool($parser);
653 if ( my $spool_dir = $ENV{PERL_TEST_HARNESS_DUMP_TAP} ) {
655 my $spool = File::Spec->catfile( $spool_dir, $test );
658 my ( $vol, $dir, undef ) = File::Spec->splitpath($spool);
659 my $path = File::Spec->catpath( $vol, $dir, '' );
660 eval { mkpath($path) };
661 $self->_croak($@) if $@;
663 my $spool_handle = IO::Handle->new;
664 open( $spool_handle, ">$spool" )
665 or $self->_croak(" Can't write $spool ( $! ) ");
667 return $spool_handle;
677 if ( my $spool_handle = $parser->delete_spool ) {
679 or $self->_croak(" Error closing TAP spool file( $! ) \n ");
686 my ( $self, $message ) = @_;
688 $message = $self->_error;
690 $self->SUPER::_croak($message);
697 If you like the C<prove> utility and L<TAP::Parser> but you want your
698 own harness, all you need to do is write one and provide C<new> and
699 C<runtests> methods. Then you can use the C<prove> utility like so:
701 prove --harness My::Test::Harness
703 Note that while C<prove> accepts a list of tests (or things to be
704 tested), C<new> has a fairly rich set of arguments. You'll probably want
705 to read over this code carefully to see how all of them are being used.
715 # vim:ts=4:sw=4:et:sta