On Mon, Dec 30, 2013 at 10:54 AM,
http://zurom.id.mail.ru/ via RT <
bug-Test-Trap@rt.cpan.org> wrote:
Show quoted text>
> I've wrote unit-test fo cgi scripts where all inner code covered by sub
> _run. And the only thing that i can test is that sub.
> And of cource the HTTP status depends on exit status, so we've got 500
> after die...
>
> So the tests should show that script ends with exit code no equal to zero.
> It is important i think
...
Show quoted text> ... and in my case the die itself is not so important as the exit status
>
Right. Assuming you have already considered and dismissed the frameworks
for tests with (real or mocked) webservers ... they can be rather heavy,
after all ...
If you're treating &_run as a black box, there is no way an ordinary exit
layer could trap all kinds of non-zero exits, so conceptually, it's
insufficient. Perl is just too powerful for a pure-purl trap to properly
contain it ...
For instance:
$ perl -e 'exec "false"'
$ echo $?
1
$ perl -MTest::Trap -e 'trap { exec "false" }; print $trap->exit // "undef"'
$ echo $?
1
(See the caveats for more ways to escape the trap.)
1) The only way to safely handle every kind of exit from black boxes, is
in a process of its own. A bit heavier and slower, but it will work. I
might even want to write up a special layer for that ... sounds like it
could be useful ... haven't needed it yet, though. And I'll need to sleep
on it, in any case. It's kinda orthogonal to what I was originally trying
to do with Test::Trap.
2) If &_run is not a black box, but you control it and the code it calls,
you could rewrite them so that they never exec(), never POSIX::_exit(),
never throw exceptions (that they don't themselves catch), perhaps never
even return, but always just exit(). Or at least, so that you know in each
(test) case whether it will return, exit, or throw an exception. And then
write the tests accordingly.
3) If it is not specified whether the code should return or exit with
zero on success, nor whether it should throw an exception or exit with
non-zero on failure, the test code must allow for either. But we cannot
safely trap every kind of exit in the standard layers. As a middle way,
you may decide to avoid troublesome exits, and just write the tests so as
to allow for either of return/exception and zero/non-zero trappable exit.
Perhaps with helpers:
sub did_succeed {
my $trap = shift;
my $name = shift // "Expecting return or zero exit value";
if ($trap->leaveby eq "exit") {
$trap->exit_is(0, $name);
}
else {
$trap->did_return($name);
}
}
sub did_fail {
my $trap = shift;
my $name = shift // "Expecting exception or non-zero exit value";
if ($trap->leaveby eq "exit") {
$trap->exit_isnt(0, $name);
}
else {
$trap->did_die($name);
}
}
... or even drop them in a C<< { package Test::Trap; ... } >> for
monkey-patched helper methods. :)
But again, this will not help you if &_run or code called from it may use
exec() or CORE::exit() or other non-pure-perl stuff, as mentioned in the
caveats. For that, a subprocess will be needed, and Test::Trap does not
(as yet) have any such mechanism.
Eirik