Right now Test::Builder::_ending() is executed only if the current process id is the one it had when it started. This prevents a child process from completing the test with the "1..N" header.
I introduced a new method, reporting_pid(), that allows the user to control which process should execute _ending(). With the change I can have a single test file that includes a fork. Then I can run it twice, once verifying the parent and a second time verifying the child. For example, the new tests included in the patch below allow the following: % perl t/reporting_pid_parent.t ok 1 - common test ok 2 - parent test 1 ok 3 - parent test 2 1..3 % env TEST_CHILD=1 perl t/reporting_pid_parent.t ok 1 - common test ok 2 - child test 1 ok 3 - child test 2 ok 4 - child test 3 ok 5 - child test 4 ok 6 - child test 5 1..6 crag% cat t/reporting_pid_child.t $ENV{TEST_CHILD} = 1; my $parent = $0; $parent =~ s/_child.t/_parent.t/; do $parent; % perl t/reporting_pid_child.t ok 1 - common test ok 2 - child test 1 ok 3 - child test 2 ok 4 - child test 3 ok 5 - child test 4 ok 6 - child test 5 1..6 Please include this code in the next release of Test::Builder. Thank you, Scott diff -ru --new-file Test-Simple-0.47/lib/Test/Builder.pm Test-Simple-0.47-patched/lib/Test/Builder.pm --- Test-Simple-0.47/lib/Test/Builder.pm Mon Aug 26 05:50:27 2002 +++ Test-Simple-0.47-patched/lib/Test/Builder.pm Sun Mar 28 16:24:12 2004 @@ -30,7 +30,7 @@ use vars qw($Level); my($Test_Died) = 0; my($Have_Plan) = 0; -my $Original_Pid = $$; +my $Reporting_Pid = $$; my $Curr_Test = 0; share($Curr_Test); my @Test_Results = (); share(@Test_Results); my @Test_Details = (); share(@Test_Details); @@ -1044,6 +1044,36 @@ select $old_fh; } +=item B<reporting_pid> + + $Test->reporting_pid($pid); + +Select which process should do final reporting. That report +includes the 1..N header when it was not generated at the start +of execution. + +Defaults to the initial parent process. + +Typically used to check both the parent and child branches of tests +that fork(). The branch that is not going to be verified during +one run can discard its test results via $self->output("/dev/null") +and $self->failure_output("/dev/null") while the verified branch +uses reporting_pid($$). Then, during the next run, the two +branches switch roles. + +See t/reporting_pid_*.t in the source code for examples. + +=cut + +sub reporting_pid { + my($self, $pid) = @_; + + if( defined $pid ) { + $Reporting_Pid = $pid; + } + return $Reporting_Pid; +} + =back @@ -1301,7 +1331,7 @@ # Don't bother with an ending if this is a forked copy. Only the parent # should do the ending. - do{ _my_exit($?) && return } if $Original_Pid != $$; + do{ _my_exit($?) && return } if $Reporting_Pid != $$; # Bailout if plan() was never called. This is so # "require Test::Simple" doesn't puke. diff -ru --new-file Test-Simple-0.47/t/reporting_pid_child.t Test-Simple-0.47-patched/t/reporting_pid_child.t --- Test-Simple-0.47/t/reporting_pid_child.t Wed Dec 31 18:00:00 1969 +++ Test-Simple-0.47-patched/t/reporting_pid_child.t Sun Mar 28 16:29:55 2004 @@ -0,0 +1,5 @@ +$ENV{TEST_CHILD} = 1; + +my $parent = $0; +$parent =~ s/_child.t/_parent.t/; +do $parent; diff -ru --new-file Test-Simple-0.47/t/reporting_pid_parent.t Test-Simple-0.47-patched/t/reporting_pid_parent.t --- Test-Simple-0.47/t/reporting_pid_parent.t Wed Dec 31 18:00:00 1969 +++ Test-Simple-0.47-patched/t/reporting_pid_parent.t Sun Mar 28 16:30:11 2004 @@ -0,0 +1,59 @@ +use strict; +use Test::Builder; +use Test::More qw(no_plan); + +my $Test = Test::Builder->new(); +ok(defined($Test), "common test"); + +# +# Split into a parent and a child. +# +my $pid = fork; +$Test->BAILOUT("Failed to fork: $!") unless defined($pid); + +# +# Using $ENV{TEST_CHILD} as our guide, decide which output messages are +# going to be discarded. Also make sure that the proper branch, parent +# or child, will do the end of run reporting in +# Test::Builder::_ending(). +# +if ($pid) { + # + # Parent + # + if ($ENV{TEST_CHILD}) { + $Test->reporting_pid($pid); + + my($discard); + open($discard, '+>', undef); + $Test->output($discard); + $Test->failure_output($discard); + } +} else { + # + # Child + # + if ($ENV{TEST_CHILD}) { + $Test->reporting_pid($$); + } else { + my($discard); + open($discard, '+>', undef); + $Test->output($discard); + $Test->failure_output($discard); + } +} + +# +# This is were the real tests could be run and results verified. +# +if ($pid) { + ok(42, "parent test 1"); + ok(24, "parent test 2"); + waitpid($pid, 0); +} else { + ok(111, "child test 1"); + ok(222, "child test 2"); + ok(333, "child test 3"); + ok(444, "child test 4"); + ok(555, "child test 5"); +}