There are some things about this interface that bother me, like the lack of
commas after the closing brace, or the use of one test for both isa and =~
testing. Those minor annoyances got to me every time I tried to use
Test::Exception, but they weren't the thing that really bugged me. That was
the use of Sub-Uplevel.

Sub::Uplevel is a library that lets you call a subroutine, but hide parts of
the call stack visible to it. In other words, if the subroutine checks the
result of caller, it won't see the real answer, but will instead see what it
would have seen, had it been called from a higher place in the stack. This
effect is accomplished by replacing CORE::GLOBAL::caller -- scary stuff
indeed. It's even a bit worse, because it has to replace it globally and then
only behave differently if uplevel is in effect.

Sub::Uplevel interacts strangely with other tricky code, and the development
branch of perl5 seems to break Sub::Uplevel more often than many other
libraries. What makes this frustrating is that in almost every case, there is
no reason for anyone to use Sub::Uplevel. It should only be used when it is
absolutely necessary that the callee not see a few stack frames. That's only
necessary when the callee has distinct behavior based on different callers, and
that behavior can't be overridden with explicit parameters. Writing code that
behaves that way is a really bad idea. Test::Exception's use of Sub::Uplevel
caters to this very small minority of awful code, at the expense of making
better distributions unstable because of their unneeded dependency on
Sub::Uplevel.

This week, I released Test::Fatal,
which is a replacement for Test::Exception. It is not a drop-in replacement,
because I didn't really care for the API of Test::Exception. Instead, it
provides only one important routine: exception.

exception is passed a code block and executes it. If the code throws an
exception, the exception is returned. Otherwise, exception returns undef.
In the event that an exception was thrown, but it is undefined or otherwise
false, Test::Fatal will die, telling you in effect, "This code can produce
the really awful case of 'died but $@ is false,' and you should either fix it
or use a more sophisticated testing mechanism for it."

This means that the sample of Test::Exception code, above, could be rewritten
as follows: