(I think I've seen the answer to this, but I can't find it again. The closest I have come across is this question).
I am hacking on prt and am trying to get full coverage data for my changes. Some of my new tests call system($^X, 'prt', ...)
to run child processes. I then test the output of those processes. However, Devel::Cover does not collect coverage data in the child processes. How do I collect that data, without causing Devel::Cover to run when I do a regular make test
? Currently I have an ugly workaround (see below), but I think there must be a simpler way.
A full MCVE is here. Command line to copy, for your convenience:
git clone https://github.com/cxw42/multi-process-devel-cover-test.git ; cd multi-process-devel-cover-test ; perl Makefile.PL ; make ; cover -test
Comment out line 11 of t/01-help.t
for the workaround described below.
Edit The reason I am using system
is to get to 100% coverage on -h
/--help
/--version
. Those switches are handled by Getopt::Long, which calls exit()
automatically. If necessary, I can use -exitval=>NOEXIT
and handle the exit in my own code.
PERL5OPT
$ PERL5OPT=-MDevel::Cover=-silent,1 cover -test
/home/cxw/perl5/perlbrew/perls/perlcygbrew-5.26.2-1/bin/cover shouldn't be run with coverage turned on.
HARNESS_PERL_SWITCHES
+cover
$ HARNESS_PERL_SWITCHES=-MDevel::Cover=-silent,1 cover -test
...
t/01-help.t .. # Devel::Cover not covering
...
----- ------ ------ ------ ------ ------ ------ ------
File stmt bran cond sub pod time total
----- ------ ------ ------ ------ ------ ------ ------
Total n/a n/a n/a n/a n/a n/a n/a
----- ------ ------ ------ ------ ------ ------ ------
HARNESS_PERL_SWITCHES
+EUMM make test
$ HARNESS_PERL_SWITCHES=-MDevel::Cover=-silent,1 make test
...
t/01-help.t .. # Devel::Cover not covering
...
$ (export HARNESS_PERL_SWITCHES=-MDevel::Cover=-silent,1 ; make test)
...
t/01-help.t .. # Devel::Cover not covering
...
At present, the only way I have found is to manually add -MDevel::Cover
to the command line when I call system
. Inspired by this answer and the corresponding tests, I have the following workaround:
# Detect whether Devel::Cover is running
my $is_covering = !!(eval 'Devel::Cover::get_coverage()');
my @perl = ($^X, $is_covering ? ('-MDevel::Cover=-silent,1') : ());
diag $is_covering ? 'Devel::Cover running' : 'Devel::Cover not covering';
# Pass the Devel::Cover option, if any, to the child process
system(@perl, 'prt', ...);
In the MCVE, the workaround is here and it is used here.
I think that this, or something similar, is probably about the best you can do.
Devel::Cover is pretty much designed as a development tool and, as such, has the assumption that you will be testing one project at a time. It seems that you are really wanting to test two projects here. If that's not the case then perhaps there is a better way of combining the parts than using system?
But if your current solution is the best way of combining this code then I'm not sure there's a better way to get complete coverage. You could perhaps be explicit and set an environment variable if you want coverage, for example, or you could set $PERL5OPT rather than change the system call, but essentially that's the same solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With