diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
commit | fc22b3d6507c6745911b9dfcc68f1e665ae13dbc (patch) | |
tree | ce1e3bce06471410239a6f41282e328770aa404a /upstream/debian-bookworm/man3/TAP::Harness.3perl | |
parent | Initial commit. (diff) | |
download | manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.tar.xz manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.zip |
Adding upstream version 4.22.0.upstream/4.22.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'upstream/debian-bookworm/man3/TAP::Harness.3perl')
-rw-r--r-- | upstream/debian-bookworm/man3/TAP::Harness.3perl | 628 |
1 files changed, 628 insertions, 0 deletions
diff --git a/upstream/debian-bookworm/man3/TAP::Harness.3perl b/upstream/debian-bookworm/man3/TAP::Harness.3perl new file mode 100644 index 00000000..492a071b --- /dev/null +++ b/upstream/debian-bookworm/man3/TAP::Harness.3perl @@ -0,0 +1,628 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "TAP::Harness 3perl" +.TH TAP::Harness 3perl "2023-11-25" "perl v5.36.0" "Perl Programmers Reference Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +TAP::Harness \- Run test scripts with statistics +.SH "VERSION" +.IX Header "VERSION" +Version 3.44 +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a simple test harness which allows tests to be run and results +automatically aggregated and output to \s-1STDOUT.\s0 +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 3 +\& use TAP::Harness; +\& my $harness = TAP::Harness\->new( \e%args ); +\& $harness\->runtests(@tests); +.Ve +.SH "METHODS" +.IX Header "METHODS" +.SS "Class Methods" +.IX Subsection "Class Methods" +\fI\f(CI\*(C`new\*(C'\fI\fR +.IX Subsection "new" +.PP +.Vb 5 +\& my %args = ( +\& verbosity => 1, +\& lib => [ \*(Aqlib\*(Aq, \*(Aqblib/lib\*(Aq, \*(Aqblib/arch\*(Aq ], +\& ) +\& my $harness = TAP::Harness\->new( \e%args ); +.Ve +.PP +The constructor returns a new \f(CW\*(C`TAP::Harness\*(C'\fR object. It accepts an +optional hashref whose allowed keys are: +.IP "\(bu" 4 +\&\f(CW\*(C`verbosity\*(C'\fR +.Sp +Set the verbosity level: +.Sp +.Vb 6 +\& 1 verbose Print individual test results to STDOUT. +\& 0 normal +\& \-1 quiet Suppress some test output (mostly failures +\& while tests are running). +\& \-2 really quiet Suppress everything but the tests summary. +\& \-3 silent Suppress everything. +.Ve +.IP "\(bu" 4 +\&\f(CW\*(C`timer\*(C'\fR +.Sp +Append run time for each test to output. Uses Time::HiRes if +available. +.IP "\(bu" 4 +\&\f(CW\*(C`failures\*(C'\fR +.Sp +Show test failures (this is a no-op if \f(CW\*(C`verbose\*(C'\fR is selected). +.IP "\(bu" 4 +\&\f(CW\*(C`comments\*(C'\fR +.Sp +Show test comments (this is a no-op if \f(CW\*(C`verbose\*(C'\fR is selected). +.IP "\(bu" 4 +\&\f(CW\*(C`show_count\*(C'\fR +.Sp +Update the running test count during testing. +.IP "\(bu" 4 +\&\f(CW\*(C`normalize\*(C'\fR +.Sp +Set to a true value to normalize the \s-1TAP\s0 that is emitted in verbose modes. +.IP "\(bu" 4 +\&\f(CW\*(C`lib\*(C'\fR +.Sp +Accepts a scalar value or array ref of scalar values indicating which +paths to allowed libraries should be included if Perl tests are +executed. Naturally, this only makes sense in the context of tests +written in Perl. +.IP "\(bu" 4 +\&\f(CW\*(C`switches\*(C'\fR +.Sp +Accepts a scalar value or array ref of scalar values indicating which +switches should be included if Perl tests are executed. Naturally, this +only makes sense in the context of tests written in Perl. +.IP "\(bu" 4 +\&\f(CW\*(C`test_args\*(C'\fR +.Sp +A reference to an \f(CW@INC\fR style array of arguments to be passed to each +test program. +.Sp +.Vb 1 +\& test_args => [\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq], +.Ve +.Sp +if you want to pass different arguments to each test then you should +pass a hash of arrays, keyed by the alias for each test: +.Sp +.Vb 4 +\& test_args => { +\& my_test => [\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq], +\& other_test => [\*(Aqbaz\*(Aq], +\& } +.Ve +.IP "\(bu" 4 +\&\f(CW\*(C`color\*(C'\fR +.Sp +Attempt to produce color output. +.IP "\(bu" 4 +\&\f(CW\*(C`exec\*(C'\fR +.Sp +Typically, Perl tests are run through this. However, anything which +spits out \s-1TAP\s0 is fine. You can use this argument to specify the name of +the program (and optional switches) to run your tests with: +.Sp +.Vb 1 +\& exec => [\*(Aq/usr/bin/ruby\*(Aq, \*(Aq\-w\*(Aq] +.Ve +.Sp +You can also pass a subroutine reference in order to determine and +return the proper program to run based on a given test script. The +subroutine reference should expect the TAP::Harness object itself as the +first argument, and the file name as the second argument. It should +return an array reference containing the command to be run and including +the test file name. It can also simply return \f(CW\*(C`undef\*(C'\fR, in which case +TAP::Harness will fall back on executing the test script in Perl: +.Sp +.Vb 2 +\& exec => sub { +\& my ( $harness, $test_file ) = @_; +\& +\& # Let Perl tests run. +\& return undef if $test_file =~ /[.]t$/; +\& return [ qw( /usr/bin/ruby \-w ), $test_file ] +\& if $test_file =~ /[.]rb$/; +\& } +.Ve +.Sp +If the subroutine returns a scalar with a newline or a filehandle, it +will be interpreted as raw \s-1TAP\s0 or as a \s-1TAP\s0 stream, respectively. +.IP "\(bu" 4 +\&\f(CW\*(C`merge\*(C'\fR +.Sp +If \f(CW\*(C`merge\*(C'\fR is true the harness will create parsers that merge \s-1STDOUT\s0 +and \s-1STDERR\s0 together for any processes they start. +.IP "\(bu" 4 +\&\f(CW\*(C`sources\*(C'\fR +.Sp +\&\fI\s-1NEW\s0 to 3.18\fR. +.Sp +If set, \f(CW\*(C`sources\*(C'\fR must be a hashref containing the names of the +TAP::Parser::SourceHandlers to load and/or configure. The values are a +hash of configuration that will be accessible to the source handlers via +\&\*(L"config_for\*(R" in TAP::Parser::Source. +.Sp +For example: +.Sp +.Vb 5 +\& sources => { +\& Perl => { exec => \*(Aq/path/to/custom/perl\*(Aq }, +\& File => { extensions => [ \*(Aq.tap\*(Aq, \*(Aq.txt\*(Aq ] }, +\& MyCustom => { some => \*(Aqconfig\*(Aq }, +\& } +.Ve +.Sp +The \f(CW\*(C`sources\*(C'\fR parameter affects how \f(CW\*(C`source\*(C'\fR, \f(CW\*(C`tap\*(C'\fR and \f(CW\*(C`exec\*(C'\fR parameters +are handled. +.Sp +For more details, see the \f(CW\*(C`sources\*(C'\fR parameter in \*(L"new\*(R" in TAP::Parser, +TAP::Parser::Source, and TAP::Parser::IteratorFactory. +.IP "\(bu" 4 +\&\f(CW\*(C`aggregator_class\*(C'\fR +.Sp +The name of the class to use to aggregate test results. The default is +TAP::Parser::Aggregator. +.IP "\(bu" 4 +\&\f(CW\*(C`version\*(C'\fR +.Sp +\&\fI\s-1NEW\s0 to 3.22\fR. +.Sp +Assume this \s-1TAP\s0 version for TAP::Parser instead of default \s-1TAP\s0 +version 12. +.IP "\(bu" 4 +\&\f(CW\*(C`formatter_class\*(C'\fR +.Sp +The name of the class to use to format output. The default is +TAP::Formatter::Console, or TAP::Formatter::File if the output +isn't a \s-1TTY.\s0 +.IP "\(bu" 4 +\&\f(CW\*(C`multiplexer_class\*(C'\fR +.Sp +The name of the class to use to multiplex tests during parallel testing. +The default is TAP::Parser::Multiplexer. +.IP "\(bu" 4 +\&\f(CW\*(C`parser_class\*(C'\fR +.Sp +The name of the class to use to parse \s-1TAP.\s0 The default is +TAP::Parser. +.IP "\(bu" 4 +\&\f(CW\*(C`scheduler_class\*(C'\fR +.Sp +The name of the class to use to schedule test execution. The default is +TAP::Parser::Scheduler. +.IP "\(bu" 4 +\&\f(CW\*(C`formatter\*(C'\fR +.Sp +If set \f(CW\*(C`formatter\*(C'\fR must be an object that is capable of formatting the +\&\s-1TAP\s0 output. See TAP::Formatter::Console for an example. +.IP "\(bu" 4 +\&\f(CW\*(C`errors\*(C'\fR +.Sp +If parse errors are found in the \s-1TAP\s0 output, a note of this will be +made in the summary report. To see all of the parse errors, set this +argument to true: +.Sp +.Vb 1 +\& errors => 1 +.Ve +.IP "\(bu" 4 +\&\f(CW\*(C`directives\*(C'\fR +.Sp +If set to a true value, only test results with directives will be +displayed. This overrides other settings such as \f(CW\*(C`verbose\*(C'\fR or +\&\f(CW\*(C`failures\*(C'\fR. +.IP "\(bu" 4 +\&\f(CW\*(C`ignore_exit\*(C'\fR +.Sp +If set to a true value instruct \f(CW\*(C`TAP::Parser\*(C'\fR to ignore exit and wait +status from test scripts. +.IP "\(bu" 4 +\&\f(CW\*(C`jobs\*(C'\fR +.Sp +The maximum number of parallel tests to run at any time. Which tests +can be run in parallel is controlled by \f(CW\*(C`rules\*(C'\fR. The default is to +run only one test at a time. +.IP "\(bu" 4 +\&\f(CW\*(C`rules\*(C'\fR +.Sp +A reference to a hash of rules that control which tests may be executed in +parallel. If no rules are declared and CPAN::Meta::YAML is available, +\&\f(CW\*(C`TAP::Harness\*(C'\fR attempts to load rules from a \s-1YAML\s0 file specified by the +\&\f(CW\*(C`rulesfile\*(C'\fR parameter. If no rules file exists, the default is for all +tests to be eligible to be run in parallel. +.Sp +Here some simple examples. For the full details of the data structure +and the related glob-style pattern matching, see +\&\*(L"Rules data structure\*(R" in TAP::Parser::Scheduler. +.Sp +.Vb 4 +\& # Run all tests in sequence, except those starting with "p" +\& $harness\->rules({ +\& par => \*(Aqt/p*.t\*(Aq +\& }); +\& +\& # Equivalent YAML file +\& \-\-\- +\& par: t/p*.t +\& +\& # Run all tests in parallel, except those starting with "p" +\& $harness\->rules({ +\& seq => [ +\& { seq => \*(Aqt/p*.t\*(Aq }, +\& { par => \*(Aq**\*(Aq }, +\& ], +\& }); +\& +\& # Equivalent YAML file +\& \-\-\- +\& seq: +\& \- seq: t/p*.t +\& \- par: ** +\& +\& # Run some startup tests in sequence, then some parallel tests than some +\& # teardown tests in sequence. +\& $harness\->rules({ +\& seq => [ +\& { seq => \*(Aqt/startup/*.t\*(Aq }, +\& { par => [\*(Aqt/a/*.t\*(Aq,\*(Aqt/b/*.t\*(Aq,\*(Aqt/c/*.t\*(Aq], } +\& { seq => \*(Aqt/shutdown/*.t\*(Aq }, +\& ], +\& +\& }); +\& +\& # Equivalent YAML file +\& \-\-\- +\& seq: +\& \- seq: t/startup/*.t +\& \- par: +\& \- t/a/*.t +\& \- t/b/*.t +\& \- t/c/*.t +\& \- seq: t/shutdown/*.t +.Ve +.Sp +This is an experimental feature and the interface may change. +.IP "\(bu" 4 +\&\f(CW\*(C`rulesfiles\*(C'\fR +.Sp +This specifies where to find a \s-1YAML\s0 file of test scheduling rules. If not +provided, it looks for a default file to use. It first checks for a file given +in the \f(CW\*(C`HARNESS_RULESFILE\*(C'\fR environment variable, then it checks for +\&\fItestrules.yml\fR and then \fIt/testrules.yml\fR. +.IP "\(bu" 4 +\&\f(CW\*(C`stdout\*(C'\fR +.Sp +A filehandle for catching standard output. +.IP "\(bu" 4 +\&\f(CW\*(C`trap\*(C'\fR +.Sp +Attempt to print summary information if run is interrupted by +\&\s-1SIGINT\s0 (Ctrl-C). +.PP +Any keys for which the value is \f(CW\*(C`undef\*(C'\fR will be ignored. +.SS "Instance Methods" +.IX Subsection "Instance Methods" +\fI\f(CI\*(C`runtests\*(C'\fI\fR +.IX Subsection "runtests" +.PP +.Vb 1 +\& $harness\->runtests(@tests); +.Ve +.PP +Accepts an array of \f(CW@tests\fR to be run. This should generally be the +names of test files, but this is not required. Each element in \f(CW@tests\fR +will be passed to \f(CW\*(C`TAP::Parser::new()\*(C'\fR as a \f(CW\*(C`source\*(C'\fR. See +TAP::Parser for more information. +.PP +It is possible to provide aliases that will be displayed in place of the +test name by supplying the test as a reference to an array containing +\&\f(CW\*(C`[ $test, $alias ]\*(C'\fR: +.PP +.Vb 2 +\& $harness\->runtests( [ \*(Aqt/foo.t\*(Aq, \*(AqFoo Once\*(Aq ], +\& [ \*(Aqt/foo.t\*(Aq, \*(AqFoo Twice\*(Aq ] ); +.Ve +.PP +Normally it is an error to attempt to run the same test twice. Aliases +allow you to overcome this limitation by giving each run of the test a +unique name. +.PP +Tests will be run in the order found. +.PP +If the environment variable \f(CW\*(C`PERL_TEST_HARNESS_DUMP_TAP\*(C'\fR is defined it +should name a directory into which a copy of the raw \s-1TAP\s0 for each test +will be written. \s-1TAP\s0 is written to files named for each test. +Subdirectories will be created as needed. +.PP +Returns a TAP::Parser::Aggregator containing the test results. +.PP +\fI\f(CI\*(C`summary\*(C'\fI\fR +.IX Subsection "summary" +.PP +.Vb 1 +\& $harness\->summary( $aggregator ); +.Ve +.PP +Output the summary for a TAP::Parser::Aggregator. +.PP +\fI\f(CI\*(C`aggregate_tests\*(C'\fI\fR +.IX Subsection "aggregate_tests" +.PP +.Vb 1 +\& $harness\->aggregate_tests( $aggregate, @tests ); +.Ve +.PP +Run the named tests and display a summary of result. Tests will be run +in the order found. +.PP +Test results will be added to the supplied TAP::Parser::Aggregator. +\&\f(CW\*(C`aggregate_tests\*(C'\fR may be called multiple times to run several sets of +tests. Multiple \f(CW\*(C`Test::Harness\*(C'\fR instances may be used to pass results +to a single aggregator so that different parts of a complex test suite +may be run using different \f(CW\*(C`TAP::Harness\*(C'\fR settings. This is useful, for +example, in the case where some tests should run in parallel but others +are unsuitable for parallel execution. +.PP +.Vb 8 +\& my $formatter = TAP::Formatter::Console\->new; +\& my $ser_harness = TAP::Harness\->new( { formatter => $formatter } ); +\& my $par_harness = TAP::Harness\->new( +\& { formatter => $formatter, +\& jobs => 9 +\& } +\& ); +\& my $aggregator = TAP::Parser::Aggregator\->new; +\& +\& $aggregator\->start(); +\& $ser_harness\->aggregate_tests( $aggregator, @ser_tests ); +\& $par_harness\->aggregate_tests( $aggregator, @par_tests ); +\& $aggregator\->stop(); +\& $formatter\->summary($aggregator); +.Ve +.PP +Note that for simpler testing requirements it will often be possible to +replace the above code with a single call to \f(CW\*(C`runtests\*(C'\fR. +.PP +Each element of the \f(CW@tests\fR array is either: +.IP "\(bu" 4 +the source name of a test to run +.IP "\(bu" 4 +a reference to a [ source name, display name ] array +.PP +In the case of a perl test suite, typically \fIsource names\fR are simply the file +names of the test scripts to run. +.PP +When you supply a separate display name it becomes possible to run a +test more than once; the display name is effectively the alias by which +the test is known inside the harness. The harness doesn't care if it +runs the same test more than once when each invocation uses a +different name. +.PP +\fI\f(CI\*(C`make_scheduler\*(C'\fI\fR +.IX Subsection "make_scheduler" +.PP +Called by the harness when it needs to create a +TAP::Parser::Scheduler. Override in a subclass to provide an +alternative scheduler. \f(CW\*(C`make_scheduler\*(C'\fR is passed the list of tests +that was passed to \f(CW\*(C`aggregate_tests\*(C'\fR. +.PP +\fI\f(CI\*(C`jobs\*(C'\fI\fR +.IX Subsection "jobs" +.PP +Gets or sets the number of concurrent test runs the harness is +handling. By default, this value is 1 \*(-- for parallel testing, this +should be set higher. +.PP +\fI\f(CI\*(C`make_parser\*(C'\fI\fR +.IX Subsection "make_parser" +.PP +Make a new parser and display formatter session. Typically used and/or +overridden in subclasses. +.PP +.Vb 1 +\& my ( $parser, $session ) = $harness\->make_parser; +.Ve +.PP +\fI\f(CI\*(C`finish_parser\*(C'\fI\fR +.IX Subsection "finish_parser" +.PP +Terminate use of a parser. Typically used and/or overridden in +subclasses. The parser isn't destroyed as a result of this. +.SH "CONFIGURING" +.IX Header "CONFIGURING" +\&\f(CW\*(C`TAP::Harness\*(C'\fR is designed to be easy to configure. +.SS "Plugins" +.IX Subsection "Plugins" +\&\f(CW\*(C`TAP::Parser\*(C'\fR plugins let you change the way \s-1TAP\s0 is \fIinput\fR to and \fIoutput\fR +from the parser. +.PP +TAP::Parser::SourceHandlers handle \s-1TAP\s0 \fIinput\fR. You can configure them +and load custom handlers using the \f(CW\*(C`sources\*(C'\fR parameter to \*(L"new\*(R". +.PP +TAP::Formatters handle \s-1TAP\s0 \fIoutput\fR. You can load custom formatters by +using the \f(CW\*(C`formatter_class\*(C'\fR parameter to \*(L"new\*(R". To configure a formatter, +you currently need to instantiate it outside of TAP::Harness and pass it in +with the \f(CW\*(C`formatter\*(C'\fR parameter to \*(L"new\*(R". This \fImay\fR be addressed by adding +a \fIformatters\fR parameter to \*(L"new\*(R" in the future. +.ie n .SS """Module::Build""" +.el .SS "\f(CWModule::Build\fP" +.IX Subsection "Module::Build" +Module::Build version \f(CW0.30\fR supports \f(CW\*(C`TAP::Harness\*(C'\fR. +.PP +To load \f(CW\*(C`TAP::Harness\*(C'\fR plugins, you'll need to use the \f(CW\*(C`tap_harness_args\*(C'\fR +parameter to \f(CW\*(C`new\*(C'\fR, typically from your \f(CW\*(C`Build.PL\*(C'\fR. For example: +.PP +.Vb 10 +\& Module::Build\->new( +\& module_name => \*(AqMyApp\*(Aq, +\& test_file_exts => [qw(.t .tap .txt)], +\& use_tap_harness => 1, +\& tap_harness_args => { +\& sources => { +\& MyCustom => {}, +\& File => { +\& extensions => [\*(Aq.tap\*(Aq, \*(Aq.txt\*(Aq], +\& }, +\& }, +\& formatter_class => \*(AqTAP::Formatter::HTML\*(Aq, +\& }, +\& build_requires => { +\& \*(AqModule::Build\*(Aq => \*(Aq0.30\*(Aq, +\& \*(AqTAP::Harness\*(Aq => \*(Aq3.18\*(Aq, +\& }, +\& )\->create_build_script; +.Ve +.PP +See \*(L"new\*(R" +.ie n .SS """ExtUtils::MakeMaker""" +.el .SS "\f(CWExtUtils::MakeMaker\fP" +.IX Subsection "ExtUtils::MakeMaker" +ExtUtils::MakeMaker does not support TAP::Harness out-of-the-box. +.ie n .SS """prove""" +.el .SS "\f(CWprove\fP" +.IX Subsection "prove" +prove supports \f(CW\*(C`TAP::Harness\*(C'\fR plugins, and has a plugin system of its +own. See \*(L"\s-1FORMATTERS\*(R"\s0 in prove, \*(L"\s-1SOURCE HANDLERS\*(R"\s0 in prove and App::Prove +for more details. +.SH "WRITING PLUGINS" +.IX Header "WRITING PLUGINS" +If you can't configure \f(CW\*(C`TAP::Harness\*(C'\fR to do what you want, and you can't find +an existing plugin, consider writing one. +.PP +The two primary use cases supported by TAP::Harness for plugins are \fIinput\fR +and \fIoutput\fR: +.IP "Customize how \s-1TAP\s0 gets into the parser" 2 +.IX Item "Customize how TAP gets into the parser" +To do this, you can either extend an existing TAP::Parser::SourceHandler, +or write your own. It's a pretty simple \s-1API,\s0 and they can be loaded and +configured using the \f(CW\*(C`sources\*(C'\fR parameter to \*(L"new\*(R". +.IP "Customize how \s-1TAP\s0 results are output from the parser" 2 +.IX Item "Customize how TAP results are output from the parser" +To do this, you can either extend an existing TAP::Formatter, or write your +own. Writing formatters are a bit more involved than writing a +\&\fISourceHandler\fR, as you'll need to understand the TAP::Parser \s-1API.\s0 A +good place to start is by understanding how \*(L"aggregate_tests\*(R" works. +.Sp +Custom formatters can be loaded configured using the \f(CW\*(C`formatter_class\*(C'\fR +parameter to \*(L"new\*(R". +.SH "SUBCLASSING" +.IX Header "SUBCLASSING" +If you can't configure \f(CW\*(C`TAP::Harness\*(C'\fR to do exactly what you want, and writing +a plugin isn't an option, consider extending it. It is designed to be (mostly) +easy to subclass, though the cases when sub-classing is necessary should be few +and far between. +.SS "Methods" +.IX Subsection "Methods" +The following methods are ones you may wish to override if you want to +subclass \f(CW\*(C`TAP::Harness\*(C'\fR. +.ie n .IP """new""" 4 +.el .IP "``new''" 4 +.IX Item "new" +.PD 0 +.ie n .IP """runtests""" 4 +.el .IP "``runtests''" 4 +.IX Item "runtests" +.ie n .IP """summary""" 4 +.el .IP "``summary''" 4 +.IX Item "summary" +.PD +.SH "REPLACING" +.IX Header "REPLACING" +If you like the \f(CW\*(C`prove\*(C'\fR utility and TAP::Parser but you want your +own harness, all you need to do is write one and provide \f(CW\*(C`new\*(C'\fR and +\&\f(CW\*(C`runtests\*(C'\fR methods. Then you can use the \f(CW\*(C`prove\*(C'\fR utility like so: +.PP +.Vb 1 +\& prove \-\-harness My::Test::Harness +.Ve +.PP +Note that while \f(CW\*(C`prove\*(C'\fR accepts a list of tests (or things to be +tested), \f(CW\*(C`new\*(C'\fR has a fairly rich set of arguments. You'll probably want +to read over this code carefully to see how all of them are being used. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Test::Harness |