I've hit a nasty (to me) difference between Test2::API::run_subtest and Test::Builder::subtest. Shout out to Matthew Horsfall for helping localize the problem. Here's my trivial reproducer:
#!perl use strict; use warnings; use Test::More; use Test2::API; my $code = sub { if (fork) { wait; cmp_ok($?, '!=', 0, "subprocess died"); } else { die "123"; }; }; my $call = $ARGV[0] ? \&Test::More::subtest : \&Test2::API::run_subtest; $call->(test => $code); done_testing; When running with Test::More... ~$ perl foo 1 # Subtest: test 123 at foo line 12. ok 1 - subprocess died 1..1 ok 1 - test 1..1 The die in the subprocess causes the child process to exit nonzero and the tests run normally. Great! This is how my tests work. When I switch them to Test2::API::run_subtest, though, I get this: ~$ perl foo 0 # test not ok 1 - test # Failed test 'test' # at foo line 17. # Caught exception in subtest: 123 at foo line 12. 1..1 not ok 1 - subprocess died # Failed test 'subprocess died' # at foo line 10. # got: 0 # expected: anything else 1..1 not ok 1 - test # Failed test 'test' # at foo line 17. 1..1 # Looks like you failed 1 test of 1. In the forked code, the die causes the subtest to end in failure *in the fork* meaning we get a repeat result for test 1: one from the child, one from the parent. Also, the child is now exiting zero instead of nonzero, despite the fact that it threw an exception. It gets worse [for me]! Above, I had a cmp_ok on $? that failed, so I had duplicate *not ok* results for test 1. If I replace that cmp_ok with a pass, I get duplicate *conflicting* results for test 1... and then the main process terminates zero. This means that the test seems to pass if you look at its $?, but the harness sees it as a failure because its total output does include failures (and non-increasing test numbers). Adding Test2::IPC does not help. The issue is not synchronising test counters, or the like. It's that I don't want the subprocess's exit to cause a subtest exit in the parent process. I think that's right: the only process that should turn exceptions into subtest fails is the process that created the subtest. a) am I wrong? b) advice on how to procede? -- rjbs
signature.asc
Description: Digital signature