如何在 运行 `cover -test` 时从子进程收集覆盖率,否则不收集覆盖率? (开发::封面)

How do I collect coverage from child processes when running `cover -test`, and not otherwise? (Devel::Cover)

(我想我已经看到了这个问题的答案,但是我找不到了。我遇到的最接近的是this question)。

我正在对 prt 进行黑客攻击,并试图为我的更改获取完整的覆盖数据。我的一些新测试调用 system($^X, 'prt', ...) 到 运行 子进程。然后我测试这些过程的输出。但是,Devel::Cover 不会收集子进程中的覆盖率数据。当我进行常规 make test 时,如何收集这些数据,而不会导致 Devel::Cover 到 运行?目前我有一个丑陋的解决方法(见下文),但我认为必须有更简单的方法。

完整的 MCVE 是 here。复制命令行,方便大家使用:

git clone https://github.com/cxw42/multi-process-devel-cover-test.git ; cd multi-process-devel-cover-test ; perl Makefile.PL ; make ; cover -test

注释掉 t/01-help.t 的第 11 行以获得下面描述的解决方法。

Edit 我使用 system 的原因是为了在 -h/--help/[=22= 上达到 100% 的覆盖率].这些开关由 Getopt::Long 处理,它会自动调用 exit()。如有必要,我可以使用 -exitval=>NOEXIT 并在我自己的代码中处理退出。

不起作用的东西

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+EUMMmake 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
...

当前解决方法

目前我找到的唯一方法是在调用system时在命令行中手动添加-MDevel::Cover。受 this answer and the corresponding tests 的启发,我有以下解决方法:

# 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', ...);

在 MCVE 中,解决方法是 here and it is used here

我认为这或类似的事情可能是您能做的最好的事情了。

Devel::Cover 几乎被设计为一种开发工具,因此,假设您将一次测试一个项目。看来你真的很想在这里测试两个项目。如果不是这种情况,那么也许有比使用系统更好的组合部件的方法?

但是,如果您当前的解决方案是组合此代码的最佳方式,那么我不确定是否有更好的方式来获得完整的覆盖范围。例如,如果您想要覆盖,您可能会明确设置一个环境变量,或者您可以设置 $PERL5OPT 而不是更改系统调用,但本质上这是相同的解决方案。