TAP::Parser - Parse TAP output
| Use Case | Command | Description |
|---|---|---|
| ๐ Create parser from file | TAP::Parser->new({ source => $file }) | Parse TAP from a file or executable source |
| ๐ Create parser from string | TAP::Parser->new({ tap => $tap_string }) | Parse TAP from a complete string |
| ๐ Create parser from command | TAP::Parser->new({ exec => [ 'ruby', 'test.rb' ] }) | Execute a command and parse its TAP output |
| ๐ Iterate results | while (my $r = $parser->next) { ... } | Fetch one parsed result at a time |
| โถ๏ธ Run full parse | $parser->run | Parse all TAP at once (uses callbacks) |
| โ Check test pass | $result->is_ok | Returns true if the test passed (TODO tests also pass) |
| ๐ Get passed tests | $parser->passed | Returns list/count of passed test numbers |
| ๐ Get failed tests | $parser->failed | Returns list/count of failed test numbers |
| ๐ Get parse errors | $parser->parse_errors | Returns list/count of TAP parse errors |
| ๐ง Check overall plan | $parser->is_good_plan | True if planned tests match run tests |
Version 3.43
use TAP::Parser;
my $parser = TAP::Parser->new( { source => $source } );
while ( my $result = $parser->next ) {
print $result->as_string;
}
TAP::Parser is designed to produce a proper parse of TAP output. For an example of how to run tests through this module, see the simple harnesses examples/.
There's a wiki dedicated to the Test Anything Protocol:
It includes the TAP::Parser Cookbook:
http://testanything.org/testing-with-tap/perl/tap::parser-cookbook.html
newmy $parser = TAP::Parser->new(\%args);
Returns a new TAP::Parser object.
The arguments should be a hashref with one of the following keys:
source โ CHANGED in 3.18 โ Preferred method of passing input. Creates a TAP::Parser::Source passed to the iterator_factory_class which creates an iterator. Mutually exclusive with tap and exec.
tap โ CHANGED in 3.18 โ Complete TAP output string. Creates a TAP::Parser::Source. Mutually exclusive with source and exec.
exec โ Array reference. Creates a TAP::Parser::Source; by default uses TAP::Parser::SourceHandler::Executable to create a TAP::Parser::Iterator::Process. Example: exec => [ '/usr/bin/ruby', 't/my_test.rb' ]. Mutually exclusive with source and tap.
The following keys are optional:
sources โ NEW to 3.18 โ Hashref of TAP::Parser::SourceHandlers to load/configure. Keys are handler names, values are config hashes. Example: sources => { Perl => { exec => '/path/to/custom/perl' }, File => { extensions => [ '.tap', '.txt' ] } }
callback โ Hashref of callbacks invoked by run method. Keys: test, plan, comment, bailout, unknown.
my %callbacks = (
test => \&test_callback,
plan => \&plan_callback,
comment => \&comment_callback,
bailout => \&bailout_callback,
unknown => \&unknown_callback,
);switches โ Array of Perl switches for Perl file sources. Example: switches => [ '-Ilib' ]
test_args โ Array reference of arguments to pass to the test program (with source or exec).
spool โ Filehandle to write a copy of all parsed TAP.
merge โ Boolean. If true, STDERR and STDOUT are merged. May cause breakage if STDERR contains TAP-like output.
grammar_class โ Defaults to TAP::Parser::Grammar.
result_factory_class โ Defaults to TAP::Parser::ResultFactory.
iterator_factory_class โ CHANGED in 3.18 โ Defaults to TAP::Parser::IteratorFactory.
nextmy $parser = TAP::Parser->new( { source => $file } );
while ( my $result = $parser->next ) {
print $result->as_string, "\n";
}
Returns parsed results one at a time. Destructive โ cannot rewind. Callbacks are issued before this returns. Each result is a subclass of TAP::Parser::Result.
run$parser->run;
Parses all TAP at once.
make_grammarCreates a new TAP::Parser::Grammar object. Customizable via grammar_class.
make_resultCreates a new TAP::Parser::Result using the TAP::Parser::ResultFactory. Customizable via result_factory_class.
make_iterator_factoryNEW to 3.18. Creates a new TAP::Parser::IteratorFactory. Customizable via iterator_factory_class.
while ( my $result = $parser->next ) {
print $result->as_string;
}
Each result is a TAP::Parser::Result subclass (referred to as result types).
TAP version 121..42pragma +strictok 3 - We should start with some foobar!# Hope we don't use up the foobar.Bail out! We ran out of foobar!... yo, this ain't TAP! ...Each result object has common methods and type-specific methods.
typeReturns the result type string (e.g., comment or test).
as_stringReturns a cleaned-up string representation. Test numbers are added if missing, directives are capitalized.
rawReturns the original parsed line of text.
is_planTrue if this is the test plan line.
is_testTrue if this is a test line.
is_commentTrue if this is a comment (usually only appears with merged STDERR).
is_bailoutTrue if this is a bailout line.
is_yamlTrue if the current item is a YAML block.
is_unknownTrue if the line could not be parsed.
is_okif ( $result->is_ok ) { ... }
Reports whether a result has passed. Non-test results return true. Useful for filtering:
my $parser = TAP::Parser->new( { source => $source } );
while ( my $result = $parser->next ) {
print $result->as_string unless $result->is_ok;
}
if ( $result->is_plan ) { ... }
plan โ Synonym for as_string.directive โ Returns the SKIP directive if present (e.g., 1..0 # SKIP: why bother?).explanation โ Returns the explanation for a SKIP directive.if ( $result->is_pragma ) { ... }
pragmas โ Returns a list of pragmas (each prefixed with + or -).if ( $result->is_comment ) { ... }
comment โ Returns the comment text.if ( $result->is_bailout ) { ... }
explanation โ Returns the text after Bail out!.No unique methods for unknown results.
if ( $result->is_test ) { ... }
ok โ Returns the literal ok or not ok text.number โ Returns the test number (auto-assigned if missing).description โ Returns the description after the test number, before any directive.directive โ Returns TODO or SKIP if present.explanation โ Returns the explanation for a TODO/SKIP directive.is_ok โ Boolean; true if test passed. TODO tests always pass.is_actual_ok โ Boolean; true if test passed regardless of TODO status.is_unplanned โ True if the test number exceeds the planned count. Unplanned tests always return false for is_ok.has_skip โ True if test had a SKIP directive.has_todo โ True if test had a TODO directive. TODO tests always pass.in_todo โ True while the most recent result was a TODO. Stays true until the next non-TODO test.After parsing, many methods are available to analyze results.
passedmy @passed = $parser->passed; # test numbers which passed
my $passed = $parser->passed; # count of tests passed
TODO tests that failed are counted as passed.
failedmy @failed = $parser->failed; # test numbers which failed
my $failed = $parser->failed; # count of tests failed
TODO tests that passed are NOT counted as failed.
actual_passedmy @actual_passed = $parser->actual_passed;
my $actual_passed = $parser->actual_passed;
Tests that actually passed regardless of TODO.
actual_okSynonym for actual_passed.
actual_failedmy @actual_failed = $parser->actual_failed;
my $actual_failed = $parser->actual_failed;
Tests that actually failed regardless of TODO.
todomy @todo = $parser->todo;
my $todo = $parser->todo;
Tests with TODO directives.
todo_passedmy @todo_passed = $parser->todo_passed;
my $todo_passed = $parser->todo_passed;
Tests that unexpectedly succeeded (TODO but passed).
todo_failedDeprecated in favor of todo_passed.
skippedmy @skipped = $parser->skipped;
my $skipped = $parser->skipped;
Tests with SKIP directives.
pragmaGet or set a pragma:
if ( $p->pragma('strict') ) { ... }
$p->pragma('strict', 1); # enable strict mode
pragmasmy @pragmas_enabled = $p->pragmas;
Get all currently enabled pragmas.
planmy $plan = $parser->plan;
Returns the test plan, if found.
good_planDeprecated. Use is_good_plan.
is_good_planif ( $parser->is_good_plan ) { ... }
True if the number of planned tests matches the number of tests run.
tests_plannedprint $parser->tests_planned;
Number of tests planned (e.g., 1..17 means 17 planned).
tests_runprint $parser->tests_run;
Number of tests actually run.
skip_allReturns the reason for skipping if all tests were skipped.
start_timeWall-clock time when the Parser was created.
end_timeWall-clock time when the end of TAP input was seen.
start_timesCPU times (like times in perlfunc) when the Parser was created.
end_timesCPU times (like times in perlfunc) when the end of TAP input was seen.
has_problemsif ( $parser->has_problems ) { ... }
Catch-all: true if any tests failed, TODO tests unexpectedly succeeded, or parse errors occurred.
version$parser->version;
TAP version number (defaults to 12 if not found).
exit$parser->exit;
Exit status of the executable (if ran).
wait$parser->wait;
Wait status of the executable. For non-executables, returns the exit status.
ignore_exit$parser->ignore_exit(1);
Tell the parser to ignore the exit status when determining pass/fail. Useful when exit status cannot be controlled.
parse_errorsmy @errors = $parser->parse_errors;
my $errors = $parser->parse_errors;
Returns parser errors. TAP errors include:
Note: Junk lines the parser doesn't recognize are NOT errors (future-proofing).
get_select_handlesGet file handles for select to check parser readiness.
delete_spoolmy $fh = $parser->delete_spool;
Delete and return the spool filehandle.
A callback key may be added to the constructor. Each callback is a subroutine reference invoked with the result as argument when run is used.
my %callbacks = (
test => \&test_callback,
plan => \&plan_callback,
comment => \&comment_callback,
bailout => \&bailout_callback,
unknown => \&unknown_callback,
);
my $aggregator = TAP::Parser::Aggregator->new;
for my $file ( @test_files ) {
my $parser = TAP::Parser->new(
{
source => $file,
callbacks => \%callbacks,
}
);
$parser->run;
$aggregator->add( $file, $parser );
}
Callbacks can also be added after construction:
$parser->callback( test => \&test_callback );
$parser->callback( plan => \&plan_callback );
Allowed callback keys (case-sensitive):
test โ Invoked if $result->is_test returns true.version โ Invoked if $result->is_version returns true.plan โ Invoked if $result->is_plan returns true.comment โ Invoked if $result->is_comment returns true.bailout โ Invoked if $result->is_unknown returns true.yaml โ Invoked if $result->is_yaml returns true.unknown โ Invoked if $result->is_unknown returns true.ELSE โ Fallback for results without a specific callback.ALL โ Always invoked after each result's specific callback.EOF โ Invoked when no more lines remain. The parser object is passed instead of a result.Example with Term::ANSIColor:
my %callbacks = (
test => sub {
my $test = shift;
if ( $test->is_ok && not $test->directive ) {
print color 'green';
}
elsif ( !$test->is_ok ) {
print color 'white on_red';
}
elsif ( $test->has_skip ) {
print color 'white on_blue';
}
elsif ( $test->has_todo ) {
print color 'white';
}
},
ELSE => sub {
print color 'black on_white';
},
ALL => sub {
print shift->as_string;
print color 'reset';
print "\n";
},
);
For an EBNF grammar, see TAP::Parser::Grammar.
Minor differences from Test::Harness:
1..2 todo 2). TAP::Parser does not; instead use inline TODO directives: not ok 2 - ... # TODOTAP::Parser reports them as parse errors (tests out of sequence) since they never ran.All TAP::* objects inherit from TAP::Object. Many classes have a SUBCLASSING section. TAP::Parser is the central "maker" โ it creates most objects in the TAP::Parser::* namespace, allowing single-point configuration.
A TAP parser consumes input from a single raw source (file, executable, database, IO handle, URI, etc.). The source is bundled into a TAP::Parser::Source, then TAP::Parser::IteratorFactory determines which TAP::Parser::SourceHandler to use. To handle new source types, create a new TAP::Parser::SourceHandler subclass and plug it in via the sources parameter. Use iterator_factory_class for custom iterator factories without subclassing TAP::Parser.
Iterators loop through the TAP stream. Default types subclass TAP::Parser::Iterator. The iterator factory delegates to the source handler. Custom iterators require subclassing TAP::Parser::Iterator.
Results are created as the parser iterates. Two options for custom result types:
result_factory_class.Override make_result for custom creation logic.
TAP::Parser::Grammar tokenizes the TAP stream and produces results. Subclass it and set grammar_class, or override make_grammar.
Many thanks to all contributors:
Report bugs or feature requests to bug-test-harness AT rt.org or via the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness. Patches are best. Anonymous checkout of latest version:
git clone git://github.com/Perl-Toolchain-Gang/Test-Harness.git
Copyright 2006-2008 Curtis "Ovid" Poe, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Generated by phpman v4.10.0-7-g98e9fd5 · Markdown · JSON · MCP Author: Che Dong Under GNU General Public License
2026-09-17 22:57 @216.73.216.6
CrawledBy Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)