.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" 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::SimpleOutput 3pm" .TH TAP::SimpleOutput 3pm "2022-06-17" "perl v5.34.0" "User Contributed Perl Documentation" .\" 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::SimpleOutput \- Simple closure\-driven TAP generator .SH "VERSION" .IX Header "VERSION" This document describes version 0.009 of TAP::SimpleOutput \- released February 14, 2017 as part of TAP-SimpleOutput. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use TAP::SimpleOutput \*(Aqcounter\*(Aq; \& \& my ($_ok, $_nok, $_skip, $_plan) = counters(); \& say $_ok\->(\*(AqTestClass has a metaclass\*(Aq); \& say $_ok\->(\*(AqTestClass is a Moose class\*(Aq); \& say $_ok\->(\*(AqTestClass has an attribute named bar\*(Aq); \& say $_ok\->(\*(AqTestClass has an attribute named baz\*(Aq); \& do { \& my ($_ok, $_nok, $_skip, $_plan) = counters(1); \& say $_ok\->(q{TestClass\*(Aqs attribute baz does TestRole::Two}); \& say $_ok\->(q{TestClass\*(Aqs attribute baz has a reader}); \& say $_ok\->(q{TestClass\*(Aqs attribute baz option reader correct}); \& say $_plan\->(); \& }; \& say $_ok\->(q{[subtest] checking TestClass\*(Aqs attribute baz}); \& say $_ok\->(\*(AqTestClass has an attribute named foo\*(Aq); \& \& # STDOUT looks like: \& ok 1 \- TestClass has a metaclass \& ok 2 \- TestClass is a Moose class \& ok 3 \- TestClass has an attribute named bar \& ok 4 \- TestClass has an attribute named baz \& ok 1 \- TestClass\*(Aqs attribute baz does TestRole::Two \& ok 2 \- TestClass\*(Aqs attribute baz has a reader \& ok 3 \- TestClass\*(Aqs attribute baz option reader correct \& 1..3 \& ok 5 \- [subtest] checking TestClass\*(Aqs attribute baz \& ok 6 \- TestClass has an attribute named foo .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" We provide one function, \f(CW\*(C`counters()\*(C'\fR, that returns a number of simple closures designed to help output \s-1TAP\s0 easily and correctly, with a minimum of fuss. .SH "FUNCTIONS" .IX Header "FUNCTIONS" .SS "counters($level)" .IX Subsection "counters($level)" When called in list context, this function returns a number of closures that each generate a different type of \s-1TAP\s0 output. It takes an optional \f(CW$level\fR that determines the indentation level (e.g. for subtests). These coderefs are all closed over the same counter variable that keeps track of how many test have been run so far; this allows them to always output the correct test number. .PP .Vb 1 \& my ($_ok, $_nok, $_skip, $_plan, $_todo, $_freeform) = counters(); \& \& $_ok\->(\*(Aqwhee\*(Aq); # returns "ok 1 \- whee" \& $_nok\->(\*(Aqboo\*(Aq); # returns "not ok 2 \- boo" \& $_skip\->(\*(Aqbaz\*(Aq); # returns "ok 3 # skip baz" \& $_todo\->($_ok\->(\*(Aqbip\*(Aq), \*(Aqdaleks\*(Aq); # returns "ok 4 \- bip # TODO daleks" \& $_plan\->(); # returns "1..4" \& $_freeform\->(\*(Aqyay\*(Aq); # returns "yay" .Ve .PP Alternatively, when called in scalar context this function returns a hashref of coderefs: .PP .Vb 1 \& my $tap = counters(); \& \& $tap\->{ok}\->(\*(Aqwhee\*(Aq); # returns "ok 1 \- whee" \& $tap\->{nok}\->(\*(Aqboo\*(Aq); # returns "not ok 2 \- boo" \& $tap\->{skip}\->(\*(Aqbaz\*(Aq); # returns "ok 3 # skip baz" \& $tap\->{todo}\->($tap\->{ok}\->(\*(Aqbip\*(Aq), \*(Aqdaleks\*(Aq); # returns "ok 4 \- bip # TODO daleks" \& $tap\->{plan}\->(); # returns "1..4" \& $tap\->{freeform}\->(\*(Aqyay\*(Aq); # returns "yay" .Ve .PP Note that calling the \f(CW$_plan\fR coderef only returns an intelligible response when called after all the output has been generated; this is analogous to using Test::More without a declared plan and \f(CW\*(C`done_testing()\*(C'\fR at the end. If you need or want to specify the plan prior to running tests, you'll need to do that manually. .PP \fIsubtests\fR .IX Subsection "subtests" .PP When \f(CW\*(C`counter()\*(C'\fR is passed an integer, the generated closures all indent themselves appropriately to indicate to the test harness / \s-1TAP\s0 parser that a subtest is being run. (Namely, each statement returned is prefaced with \&\f(CW\*(C`$level * 4\*(C'\fR spaces.) It's recommended that you use distinct lexical scopes for subtests to allow the usage of the same variable names (why make things difficult?) without clobbering any existing ones and to ensure that the subtest closures are not inadvertently used at an upper level. .PP .Vb 12 \& my ($_ok, $_nok) = counters(); \& $_ok\->(\*(Aqyay!\*(Aq); \& $_nok\->(\*(Aqboo :(\*(Aq); \& do { \& my ($_ok, $_nok, $_skip, $_plan) = counters(1); \& $_ok\->(\*(Aqthing 1 good\*(Aq); \& $_ok\->(\*(Aqthing 2 good\*(Aq); \& $_ok\->(\*(Aqthing 3 good\*(Aq); \& $_skip\->(\*(Aqover there\*(Aq); \& $_plan\->(); \& }; \& $_ok\->(\*(Aqsubtest passed\*(Aq); \& \& # returns \& ok 1 \- yay! \& not ok 2 \- boo :( \& ok 1 \- thing 1 good \& ok 2 \- thing 2 good \& ok 3 \- thing 3 good \& ok 4 # skip over there \& 1..4 \& ok 3 \- subtest passed .Ve .SS "counters_as_hashref" .IX Subsection "counters_as_hashref" Same as \fBcounters()\fR, except that we return a hashref rather than a list, where the keys are \*(L"ok\*(R", \*(L"nok\*(R", \*(L"skip\*(R", \*(L"plan\*(R", \*(L"todo\*(R", and \*(L"freeform\*(R", and the values are the corresponding coderefs. .SS "counters_and_levelset($level)" .IX Subsection "counters_and_levelset($level)" Acts as \fBcounters()\fR, except returns an additional coderef that can be used to adjust the level of the counters. .PP This is not something you're likely to need. .SS "\fBsubtest_header_needed()\fP" .IX Subsection "subtest_header_needed()" Returns true if the level of Test::More available will output a subtest header. .PP Note that this function will attempt to load Test::More and Perl::Version. If either of these packages are unavailable, it will \*(L"croak\*(R" in Carp. .SS "\fBsubtest_header()\fP" .IX Subsection "subtest_header()" Given an output coderef (e.g. the 'freeform' from \fBcounters()\fR or \&\fBcounters_as_hashref()\fR) and a subtest name (that is, a string), we return a subtest header appropriately indented for the level of Test::More available. .PP e.g. .PP .Vb 1 \& my $out = counters_as_hashref(); \& \& say subtest_header $out\->{freeform} => \*(AqOur subtest name!\*(Aq; \& \& # given a hashref, look for the coderef in the \*(Aqfreeform\*(Aq slot \& say subtest_header $out => \*(AqOur subtest name!\*(Aq; \& \& # or with the reviled Test::Builder::Tester: \& test_out subtest_header($out => \*(AqOur subtest name!\*(Aq) \& if subtest_header_needed; .Ve .PP Returns true if the level of Test::More available will output a subtest header. .PP Note that this function will attempt to load Test::More and Perl::Version. If either of these packages are unavailable, it will \&\*(L"croak\*(R" in Carp. .SH "USAGE WITH Test::Builder::Tester" .IX Header "USAGE WITH Test::Builder::Tester" This package was created from code I was using to make it easier to test my test packages with Test::Builder::Tester: .PP .Vb 4 \& test_out $_ok\->(\*(AqTestClass has a metaclass\*(Aq); \& test_out $_ok\->(\*(AqTestClass is a Moose class\*(Aq); \& test_out $_ok\->(\*(AqTestClass has an attribute named bar\*(Aq); \& test_out $_ok\->(\*(AqTestClass has an attribute named baz\*(Aq); .Ve .PP Once I realized I was using the exact same code (perhaps at different points in time) in multiple packages, the decision to break it out became pretty easy to make. .SH "SUBTESTS" .IX Header "SUBTESTS" Subtest formatting can be done by passing an integer \*(L"level\*(R" parameter to \&\f(CW\*(C`counter()\*(C'\fR; see the function's documentation for details. .SH "SEE ALSO" .IX Header "SEE ALSO" Please see those modules/websites for more information related to this module. .IP "\(bu" 4 Test::Builder::Tester .IP "\(bu" 4 TAP::Harness .SH "BUGS" .IX Header "BUGS" Please report any bugs or feature requests on the bugtracker website .PP When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. .SH "AUTHOR" .IX Header "AUTHOR" Chris Weyl .SS "I'm a material boy in a material world" .IX Subsection "I'm a material boy in a material world" Please note \fBI do not expect to be gittip'ed or flattr'ed for this work\fR, rather \fBit is simply a very pleasant surprise\fR. I largely create and release works like this because I need them or I find it enjoyable; however, don't let that stop you if you feel like it ;) .PP Flattr , Gratipay , or indulge my Amazon Wishlist ... If and *only* if you so desire. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is Copyright (c) 2012 by Chris Weyl. .PP This is free software, licensed under: .PP .Vb 1 \& The GNU Lesser General Public License, Version 2.1, February 1999 .Ve