TAP::S...eOutput(3pm)

πŸ“¦
version 0.009 Β· 4 versions
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

🌸 NAME 🌸

okay so bestie, this is the manual for TAP::SimpleOutput β€” the module whose whole personality is being a Simple closure-driven TAP generator. yes that's the real name, no notes. πŸ’…


✨ VERSION ✨

this doc is describing version 0.009 of TAP::SimpleOutput β€” it dropped on February 14, 2017, and it ships as part of TAP-SimpleOutput. valentine's day release, iconic behavior πŸ’–


πŸŽ€ SYNOPSIS πŸŽ€

like, look at her go:

use TAP::SimpleOutput 'counter';

my ($_ok, $_nok, $_skip, $_plan) = counters();
say $_ok->('TestClass has a metaclass');
say $_ok->('TestClass is a Moose class');
say $_ok->('TestClass has an attribute named bar');
say $_ok->('TestClass has an attribute named baz');
do {
    my ($_ok, $_nok, $_skip, $_plan) = counters(1);
    say $_ok->(q{TestClass's attribute baz does TestRole::Two});
    say $_ok->(q{TestClass's attribute baz has a reader});
    say $_ok->(q{TestClass's attribute baz option reader correct});
    say $_plan->();
};
say $_ok->(q{[subtest] checking TestClass's attribute baz});
say $_ok->('TestClass has an attribute named foo');

# 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's attribute baz does TestRole::Two
    ok 2 - TestClass's attribute baz has a reader
    ok 3 - TestClass's attribute baz option reader correct
    1..3
ok 5 - [subtest] checking TestClass's attribute baz
ok 6 - TestClass has an attribute named foo

πŸ¦‹ DESCRIPTION πŸ¦‹

so there's literally one function: counters(). she hands you back a bunch of lil closures whose entire job is to spit out TAP output easily and correctly, with the absolute minimum of fuss. that's it. that's the pitch. slay. ✨


πŸ’– FUNCTIONS πŸ’–

🌈 counters($level)

when you call her in list context, she returns a bunch of closures, and each one generates a different flavor of TAP output. she takes an optional $level that sets the indentation level (think: subtests, bestie).

and here's the cute part β€” all these coderefs are closed over the same counter variable that keeps track of how many tests have been run so far. which means they always output the correct test number. no cap, no manual bookkeeping. πŸ‘‘

my ($_ok, $_nok, $_skip, $_plan, $_todo, $_freeform) = counters();

$_ok->('whee');                    # returns "ok 1 - whee"
$_nok->('boo');                    # returns "not ok 2 - boo"
$_skip->('baz');                   # returns "ok 3 # skip baz"
$_todo->($_ok->('bip'), 'daleks'); # returns "ok 4 - bip # TODO daleks"
$_plan->();                        # returns "1..4"
$_freeform->('yay');               # returns "yay"

OR, when you call her in scalar context, she gives you back a hashref of coderefs instead:

my $tap = counters();

$tap->{ok}->('whee');                          # returns "ok 1 - whee"
$tap->{nok}->('boo');                          # returns "not ok 2 - boo"
$tap->{skip}->('baz');                         # returns "ok 3 # skip baz"
$tap->{todo}->($tap->{ok}->('bip'), 'daleks'); # returns "ok 4 - bip # TODO daleks"
$tap->{plan}->();                              # returns "1..4"
$tap->{freeform}->('yay');                     # returns "yay"
🚨 bestie listen: calling the $_plan coderef only gives you an intelligible response when you call it after all the output has been generated. it's the same energy as using Test::More without a declared plan plus "done_testing()" at the end. if you need or want to specify the plan before running tests, you're gonna have to do that manually. sorry babe.

🫢 subtests

when "counter()" gets passed an integer, all the generated closures indent themselves appropriately β€” that's how they signal to the test harness / TAP parser that a subtest is running. (specifically: every statement returned gets prefaced with "$level * 4" spaces. math girlie behavior fr fr.)

it's recommended that you use distinct lexical scopes for subtests so you can reuse the same variable names (why make things difficult, honestly?) without clobbering any existing ones β€” and also so you don't accidentally use the subtest closures up at an upper level. πŸ’€

my ($_ok, $_nok) = counters();
$_ok->('yay!');
$_nok->('boo :(');
do {
    my ($_ok, $_nok, $_skip, $_plan) = counters(1);
    $_ok->('thing 1 good');
    $_ok->('thing 2 good');
    $_ok->('thing 3 good');
    $_skip->('over there');
    $_plan->();
};
$_ok->('subtest passed');

# 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

🌟 counters_as_hashref

same as counters(), except she returns a hashref instead of a list. the keys are "ok", "nok", "skip", "plan", "todo", and "freeform", and the values are the corresponding coderefs. easy. ✨

πŸŽ€ counters_and_levelset($level)

acts as counters(), except she also returns an additional coderef that you can use to adjust the level of the counters.

ngl, this is not something you're likely to need. πŸ™ˆ

πŸ’… subtest_header_needed()

returns true if the level of Test::More available will output a subtest header.

⚠️ heads up: this function will attempt to load Test::More and Perl::Version. if either of those packages are unavailable, it will "croak" in Carp. that's a whole vibe and not the fun kind 😭

⭐ subtest_header()

give her an output coderef (like the 'freeform' from counters() or counters_as_hashref()) plus a subtest name (that is, a string), and she returns a subtest header appropriately indented for the level of Test::More available.

e.g.

my $out = counters_as_hashref();

say subtest_header $out->{freeform} => 'Our subtest name!';

# given a hashref, look for the coderef in the 'freeform' slot
say subtest_header $out => 'Our subtest name!';

# or with the reviled Test::Builder::Tester:
test_out subtest_header($out => 'Our subtest name!')
    if subtest_header_needed;

returns true if the level of Test::More available will output a subtest header.

⚠️ and same warning as before, because it's literally the same note: this function will attempt to load Test::More and Perl::Version. if either of those packages are unavailable, it will "croak" in Carp.

πŸ”₯ USAGE WITH Test::Builder::Tester πŸ”₯

this whole package was born out of code the author was already using to make testing his test packages easier with Test::Builder::Tester:

test_out $_ok->('TestClass has a metaclass');
test_out $_ok->('TestClass is a Moose class');
test_out $_ok->('TestClass has an attribute named bar');
test_out $_ok->('TestClass has an attribute named baz');

once he realized he was using the exact same code (maybe at different points in time, whatever) across multiple packages, the decision to break it out into its own thing became pretty easy to make. main character origin story tbh. πŸ‘‘


🌸 SUBTESTS 🌸

subtest formatting can be done by passing an integer "level" parameter to "counter()". see the function's documentation for details. iykyk πŸ’–


🌈 SEE ALSO 🌈

please see those modules/websites for more info related to this module:

  • Test::Builder::Tester
  • TAP::Harness

πŸ’€ BUGS πŸ’€

please report any bugs or feature requests on the bugtracker website:

https://github.com/RsrchBoy/tap-simpleoutput/issues

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. receipts, basically. 🫢


πŸ‘‘ AUTHOR πŸ‘‘

Chris Weyl <cweyl@alumni.drew.edu>

πŸ’œ I'm a material boy in a material world

please note he does not expect to be gittip'ed or flattr'ed for this work β€” rather it's just a very pleasant surprise. he largely creates and releases works like this because he needs them or finds it enjoyable; however, don't let that stop you if you feel like it ;)

...if and only if you so desire. πŸŽ€


this software is Copyright (c) 2012 by Chris Weyl.

this is free software, licensed under:

The GNU Lesser General Public License, Version 2.1, February 1999

okay that's the whole page bestie, and before you go β€” this one's signed off as perl v5.34.0, dated 2022-06-17, under the title TAP::S...eOutput(3pm) πŸ’–βœ¨ go forth and generate TAP, you absolute icon 🫢