Test::Abortable(3pm)
π¦ Test::Abortable β the perl module, bestie β¨
okay so this is Test::Abortable, straight out of the User Contributed Perl Documentation section (that's the 3pm part, iykyk π
). It's the module that lets your subtests die dramatically and then, like, get back up. resilient queen behavior honestly π
β¨ NAME β¨
Test::Abortable β subtests that you can die your way out of ... but survive π«Ά
πΈ VERSION πΈ
version 0.003 β she's tiny, she's iconic
π OVERVIEW π
So Test::Abortable gives you a whole little system for catching some exceptions and turning them into test events. Not all of them. Some. We'll get to that, bestie, don't rush me π
Like, look at this code:
use Test::More;
use Test::Abortable;
use My::API; # code under test
my $API = My::API->client;
subtest "collection distinction" => sub {
my $result = $API->do_first_thing;
is($result->documents->first->title, "The Best Thing");
isnt($result->documents->last->title, "The Best Thing");
};
subtest "document transcendence" => sub { ... };
subtest "semiotic multiplexing" => sub { ... };
subtest "homoiousios type vectors" => sub { ... };
done_testing;
Okay so in this code, $result->documents is a collection. And it's got this first method that will straight up throw an exception if the collection is empty π
And the way that wrecks us? If that happens, our whole test program dies. Not just one subtest β the program. All the other subtests never even get to run. they never got their moment π
We would much rather just abort the one subtest. Like, respectfully, only that one.
And yeah, we could do it a bunch of ways, for example by adding:
return fail("no documents in response") if $result->documents->is_empty;
β¦but that gets less and less practical the more places there are that might throw these kinds of exceptions. The list grows. The vibe declines. Not cute.
So to minimize code that basically boils down to "and then stop unless it makes sense to go on," Test::Abortable gives you a way to communicate β via exceptions β that the running subtest should be aborted, possibly with some test output attached, and that the program should then just... keep going. main character energy, the show continues π
Here's what it actually gives you:
Test::Abortableexports asubtestroutine that behaves like the one inTest::More, except it will handle and recover from abortable exceptions (defined in a sec, bestie, patience).- It also exports
testeval, which behaves like a blockevalthat only catches abortable exceptions.
now. for an exception to be "abortable" in this sense, it has to respond to a as_test_abort_events method. That's the whole vibe check. π
This method must return an arrayref of arrayrefs that describe the Test2 events to emit when the exception gets caught. So like, the exception thrown by our sample code up there might have a as_test_abort_events method that returns:
[
[ Ok => (pass => 0, name => "->first called on empty collection") ],
]
and it's totally permissible to have:
- passing
Okevents β - or only
Diagevents π - or multiple events π
- or none π«₯ β though ngl, providing none might lead to some serious confusion
Right now, any exception that provides this method will be honored. In the future, a facility for only allowing abortable exceptions of a given class may be added. so, like, watch this space β¨
π§ PERL VERSION π§
This library should run on perls released even a long time ago. It should work on any version of perl released in the last five years. grandma perl friendly, we love to see it π«Ά
Although it may work on older versions of perl, no guarantee is made that the minimum required version will not be increased. The version may be increased for any reason, and there is no promise that patches will be accepted to lower the minimum required perl.
so basically: don't come for her about the floor, she reserves the right to raise it π
π FUNCTIONS π
β subtest
subtest "do some stuff" => sub {
do_things;
do_stuff;
do_actions;
};
This routine looks just like Test::More's subtest and acts just like it, too β with one difference, bestie:
the code item passed in is executed in a block eval, and any exception thrown is checked for as_test_abort_events.
And then it's a whole little branching situation:
- If there's no exception, it returns normally. all good, no notes β¨
- If there's an abortable exception, the events are sent to the test hub and the subtest finishes normally. she survives!! π¦
- If there's a non-abortable exception, it is rethrown. we are not catching that one, that's above our pay grade π
β testeval
my $result = testeval {
my $x = get_the_x;
my $y = acquire_y;
return $x * $y;
};
testeval behaves like eval, but it only catches abortable exceptions.
So if the code you pass to testeval throws an abortable exception, testeval will return false and put the exception into $@. And other exceptions? Those are propagated. not our problem, they keep moving πΆββοΈ
π EXCEPTION IMPLEMENTATIONS π
okay crucial info: you do not need to use an exception class provided by Test::Abortable to build abortable exceptions. This is by design. In fact, Test::Abortable doesn't ship with any abortable exception classes at all. zero. none. it's giving minimalist β¨
You should just add a as_test_abort_events where it's useful and appropriate. that's it. that's the whole ask.
Here are two possible simple implementations of trivial abortable exception classes:
number one β using plain old vanilla objects:
package Abort::Test {
sub as_test_abort_events ($self) {
return [ [ Ok => (pass => 0, name => $self->{message}) ] ];
}
}
sub abort ($message) { die bless { message => $message }, 'Abort::Test' }
This works! π but if those exceptions ever get caught somewhere else, you'll be in a bunch of pain, because they've got no stack trace, no stringification behavior, and so on. lowkey tragic. they're naked exceptions. π
number two β for a more robust but still tiny implementation, you might consider failures:
use failures 'testabort';
sub failure::testabort::as_test_abort_events ($self) {
return [ [ Ok => (pass => 0, name => $self->msg) ] ];
}
For whatever it's worth, the author's intent is to add as_test_abort_events methods to his code through the use of application-specific Moose roles. that's the dream, that's the plan π
π AUTHOR π
Ricardo SIGNES <cpan@semiotic.systems>
π CONTRIBUTOR π
Ricardo Signes <rjbs@semiotic.systems>
π COPYRIGHT AND LICENSE π
This software is copyright (c) 2016 by Ricardo SIGNES.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
and that's the whole page bestie, no cap π«Ά it's Test::Abortable version 0.003, and it ships as perl v5.40.1 dated 2025-05-04 β go forth and let your subtests survive their little meltdowns πβ¨
π¦ where this page comes from
- debian trixie: libtest-abortable-perl 0.003-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libtest-abortable-perl 0.003-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libtest-abortable-perl 0.003-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms