Test::Fatal(3)
π NAME π
Test::Fatal β the absolute most incredibly simple helpers for testing code with exceptions. That's the whole vibe, bestie, and it ate. π
β¨ VERSION β¨
version 0.018 β iconic, no cap. π
πΈ SYNOPSIS πΈ
use Test::More;
use Test::Fatal;
use System::Under::Test qw(might_die);
is(
exception { might_die; },
undef,
"the code lived",
);
like(
exception { might_die; },
qr/turns out it died/,
"the code died as expected",
);
isa_ok(
exception { might_die; },
'Exception::Whatever',
'the thrown exception',
);
π¦ DESCRIPTION π¦
So Test::Fatal is the alternative to the very popular Test::Exception. It does way less, but the whole point is that it gives you more flexibility when you're testing code that throws exceptions, and you type about the same amount either way. Lowkey a steal. π
It exports exactly one routine by default: exception. That's it. One. π«Ά
Achtung! β οΈexceptionintentionally does not mess with the call stack. So if you're writing your own test functions that useexception, you must be careful about false positives β specifically when exceptions use stack traces that show arguments. If you want the more magical approach wherecallergets globally overridden, go look atTest::Exceptioninstead. π
π PERL VERSION π
This library should run on perls released, like, even a long time ago. It should work on any version of perl released in the last five years. β¨
Although it may work on older versions of perl, there is no guarantee that the minimum required version won't get bumped. The version may be increased for literally any reason, and there's no promise that patches will be accepted to lower the minimum required perl. So don't come for me. π
π FUNCTIONS π
β exception β
my $exception = exception { ... };
exception takes a bare block of code and hands you back the exception that block threw. If nothing got thrown at all, it returns undef. Easy. Slay. π
Achtung! π¨ If the block results in an unblessed false exception β like0or the empty string βTest::Fatalitself will die. And honestly? Since either of those cases signals a serious problem with the system under testing, this behavior is considered a feature. Note that this issue is only known to happen on perls before5.14. π
Be careful if you must test for those conditions: wrapping exception { ... } in an ok() block will not give you the result you need, so make sure you use is() instead. You can also just directly use Try::Tiny's try/catch mechanism β that's the underlying exception handling system of Test::Fatal. iykyk. π§
Important: there is no TAP assert being performed. In other words, no ok or not ok line gets emitted. It's up to you to use the rest of exception inside an existing test like ok, isa_ok, is, et cetera. Or you might wanna use the dies_ok and lives_ok wrappers, which do give you TAP output. π
exception does not alter the stack presented to the called block β meaning if the exception that comes back has a stack trace, it will include some frames between the code calling exception and the thing throwing the exception. This is considered a feature because it avoids the occasionally twitchy Sub::Uplevel mechanism. π
Achtung! π This is not a great idea:
sub exception_like(&$;$) {
my ($code, $pattern, $name) = @_;
like( &exception($code), $pattern, $name );
}
exception_like(sub { }, qr/foo/, 'foo appears in the exception');
If the code in the ... is gonna throw a stack trace with the arguments to each subroutine in its call stack (for example via Carp::confess), then the test name β foo appears in the exception β will itself be matched by the regex. Instead, write this:
like( exception { ... }, qr/foo/, 'foo appears in the exception' );
If you really want a test function that passes the test name, wrap the arguments in an array reference so the literal text gets hidden from a stack trace: π«Ά
sub exception_like(&$) {
my ($code, $args) = @_;
my ($pattern, $name) = @$args;
like( &exception($code), $pattern, $name );
}
exception_like(sub { }, [ qr/foo/, 'foo appears in the exception' ] );
To help avoid that whole problem where the pattern shows up in the exception because of the call stack, $Carp::MaxArgNums is locally set to -1 when the code block gets called. If you really don't want that, just set it back to whatever value you like at the beginning of the code block. Obviously, this solution doesn't affect all the possible ways that args of subroutines in the call stack might taint the test. The intention here is to prevent some false passes from people who didn't read the documentation. Your punishment for reading it is that you must consider whether to do anything about this. π (that's the deal, bestie, I don't make the rules)
Achtung: one final bad idea π©
isnt( exception { ... }, undef, "my code died!");
Sure, it's true that this tests that your code died. But you should really be testing that it died for the right reason. Like, if you make an unrelated mistake in the block β say, using the wrong dereference β your test will pass even though the code to be tested isn't really run at all. If you're expecting an inspectable exception with an identifier or a class, test that. If you're expecting a string exception, consider using like. Periodt. π
πΈ success πΈ
try {
should_live;
} catch {
fail("boo, we died");
} success {
pass("hooray, we lived");
};
success, which is exported only by request, is a Try::Tiny helper with semantics identical to finally β except the body of the block will only run if the try block ran without error. π
Even though pretty much any exception test you need can be done with exception, success blocks can sometimes help you organize complex testing. It's giving β¨organizationβ¨.
π¦ dies_ok π¦
π¦ lives_ok π¦
Exported only by request, these two functions run a given block of code and provide TAP output telling you whether it did, or did not, throw an exception. These give you an easy upgrade path for replacing existing unit tests that are based on Test::Exception. π₯
RJBS does not suggest using these except as a convenience while you're porting tests over to use Test::Fatal's exception routine. Just so we're clear. π
use Test::More tests => 2;
use Test::Fatal qw(dies_ok lives_ok);
dies_ok { die "I failed" } 'code that fails';
lives_ok { return "I'm still alive" } 'code that does not fail';
π AUTHOR π
Ricardo Signes <cpan@semiotic.systems> β the main character, honestly. π«Ά
π CONTRIBUTORS π
- David Golden <dagolden@cpan.org>
- Graham Knop <haarg@haarg.org>
- Jesse Luehrs <doy@tozt.net>
- Joel Bernstein <joel@fysh.org>
- Karen Etheridge <ether@cpan.org>
- Ricardo Signes <rjbs@semiotic.systems>
π COPYRIGHT AND LICENSE π
This software is copyright (c) 2010 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. π
okay that's the whole page, bestie, thanks for reading all the way through, you ate that πβ¨ this was Test::Fatal(3) from the User Contributed Perl Documentation, version 0.018, brought to you by perl v5.42.0 on 2026-01-17 β love u, go write some tests π
ππ¦
π¦ where this page comes from
- fedora 44: perl-Test-Fatal 0.018-2.fc44 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms