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 );
333 $self->aggregate_tests( $aggregate, @tests );
334 $self->formatter->summary($aggregate);
335 $self->_make_callback( 'after_runtests', $aggregate );
340 =head3 C<aggregate_tests>
342 $harness->aggregate_tests( $aggregate, @tests );
344 Tests will be run in the order found.
349 my ( $self, $aggregate, $test, $parser ) = @_;
351 $self->_make_callback( 'after_test', $test, $parser );
352 $aggregate->add( $test->[1], $parser );
355 sub _aggregate_forked {
356 my ( $self, $aggregate, @tests ) = @_;
358 eval { require Parallel::Iterator };
360 croak "Parallel::Iterator required for --fork option ($@)"
363 my $iter = Parallel::Iterator::iterate(
364 { workers => $self->jobs || 0 },
366 my ( $id, $test ) = @_;
368 my ( $parser, $session ) = $self->make_parser($test);
370 while ( defined( my $result = $parser->next ) ) {
371 exit 1 if $result->is_bailout;
374 $self->finish_parser( $parser, $session );
376 # Can't serialise coderefs...
377 delete $parser->{_iter};
378 delete $parser->{_stream};
379 delete $parser->{_grammar};
385 while ( my ( $id, $parser ) = $iter->() ) {
386 $self->_after_test( $aggregate, $tests[$id], $parser );
392 sub _aggregate_parallel {
393 my ( $self, $aggregate, @tests ) = @_;
395 my $jobs = $self->jobs;
396 my $mux = TAP::Parser::Multiplexer->new;
400 # Keep multiplexer topped up
401 while ( @tests && $mux->parsers < $jobs ) {
402 my $test = shift @tests;
403 my ( $parser, $session ) = $self->make_parser($test);
404 $mux->add( $parser, [ $session, $test ] );
407 if ( my ( $parser, $stash, $result ) = $mux->next ) {
408 my ( $session, $test ) = @$stash;
409 if ( defined $result ) {
410 $session->result($result);
411 exit 1 if $result->is_bailout;
415 # End of parser. Automatically removed from the mux.
416 $self->finish_parser( $parser, $session );
417 $self->_after_test( $aggregate, $test, $parser );
426 sub _aggregate_single {
427 my ( $self, $aggregate, @tests ) = @_;
429 for my $test (@tests) {
430 my ( $parser, $session ) = $self->make_parser($test);
432 while ( defined( my $result = $parser->next ) ) {
433 $session->result($result);
434 if ( $result->is_bailout ) {
436 # Keep reading until input is exhausted in the hope
437 # of allowing any pending diagnostics to show up.
438 1 while $parser->next;
443 $self->finish_parser( $parser, $session );
444 $self->_after_test( $aggregate, $test, $parser );
450 sub aggregate_tests {
451 my ( $self, $aggregate, @tests ) = @_;
453 my $jobs = $self->jobs;
455 my @expanded = map { 'ARRAY' eq ref $_ ? $_ : [ $_, $_ ] } @tests;
457 # Formatter gets only names
458 $self->formatter->prepare( map { $_->[1] } @expanded );
461 if ( $self->jobs > 1 ) {
463 $self->_aggregate_forked( $aggregate, @expanded );
466 $self->_aggregate_parallel( $aggregate, @expanded );
470 $self->_aggregate_single( $aggregate, @expanded );
480 Returns the number of concurrent test runs the harness is handling. For the default
481 harness this value is always 1. A parallel harness such as L<TAP::Harness::Parallel>
482 will override this to return the number of jobs it is handling.
486 If true the harness will attempt to fork and run the parser for each
487 test in a separate process. Currently this option requires
488 L<Parallel::Iterator> to be installed.
492 ##############################################################################
496 C<TAP::Harness> is designed to be (mostly) easy to subclass. If you don't
497 like how a particular feature functions, just override the desired methods.
501 TODO: This is out of date
503 The following methods are ones you may wish to override if you want to
504 subclass C<TAP::Harness>.
508 $harness->summary( \%args );
510 C<summary> prints the summary report after all tests are run. The argument is
511 a hashref with the following keys:
517 This is created with C<< Benchmark->new >> and it the time the tests started.
518 You can print a useful summary time, if desired, with:
520 $self->output(timestr( timediff( Benchmark->new, $start_time ), 'nop' ));
524 This is an array reference of all test names. To get the L<TAP::Parser>
525 object for individual tests:
527 my $aggregate = $args->{aggregate};
528 my $tests = $args->{tests};
530 for my $name ( @$tests ) {
531 my ($parser) = $aggregate->parsers($test);
532 ... do something with $parser
535 This is a bit clunky and will be cleaned up in a later release.
541 sub _get_parser_args {
542 my ( $self, $test ) = @_;
543 my $test_prog = $test->[0];
546 @switches = $self->lib if $self->lib;
547 push @switches => $self->switches if $self->switches;
548 $args{switches} = \@switches;
549 $args{spool} = $self->_open_spool($test_prog);
550 $args{merge} = $self->merge;
551 $args{exec} = $self->exec;
553 if ( my $exec = $self->exec ) {
554 $args{exec} = [ @$exec, $test_prog ];
557 $args{source} = $test_prog;
560 if ( defined( my $test_args = $self->test_args ) ) {
561 $args{test_args} = $test_args;
567 =head3 C<make_parser>
569 Make a new parser and display formatter session. Typically used and/or
570 overridden in subclasses.
572 my ( $parser, $session ) = $harness->make_parser;
578 my ( $self, $test ) = @_;
580 my $args = $self->_get_parser_args($test);
581 $self->_make_callback( 'parser_args', $args, $test );
582 my $parser = TAP::Parser->new($args);
584 $self->_make_callback( 'made_parser', $parser, $test );
585 my $session = $self->formatter->open_test( $test->[1], $parser );
587 return ( $parser, $session );
590 =head3 C<finish_parser>
592 Terminate use of a parser. Typically used and/or overridden in
593 subclasses. The parser isn't destroyed as a result of this.
598 my ( $self, $parser, $session ) = @_;
600 $session->close_test;
601 $self->_close_spool($parser);
610 if ( my $spool_dir = $ENV{PERL_TEST_HARNESS_DUMP_TAP} ) {
612 my $spool = File::Spec->catfile( $spool_dir, $test );
615 my ( $vol, $dir, undef ) = File::Spec->splitpath($spool);
616 my $path = File::Spec->catpath( $vol, $dir, '' );
617 eval { mkpath($path) };
618 $self->_croak($@) if $@;
620 my $spool_handle = IO::Handle->new;
621 open( $spool_handle, ">$spool" )
622 or $self->_croak(" Can't write $spool ( $! ) ");
624 return $spool_handle;
634 if ( my $spool_handle = $parser->delete_spool ) {
636 or $self->_croak(" Error closing TAP spool file( $! ) \n ");
643 my ( $self, $message ) = @_;
645 $message = $self->_error;
647 $self->SUPER::_croak($message);
654 If you like the C<prove> utility and L<TAP::Parser> but you want your
655 own harness, all you need to do is write one and provide C<new> and
656 C<runtests> methods. Then you can use the C<prove> utility like so:
658 prove --harness My::Test::Harness
660 Note that while C<prove> accepts a list of tests (or things to be
661 tested), C<new> has a fairly rich set of arguments. You'll probably want
662 to read over this code carefully to see how all of them are being used.
672 # vim:ts=4:sw=4:et:sta