如何多次运行PHP单元并连接覆盖率报告


how to run php unit multiple times and concatenate the coverage report?

我测试的代码充满了最终的静态类。 虽然我们无法重构它以获得更好的测试,但我有一个中间解决方案,可以在它自己的进程上运行几个小测试。 一切正常。 但是我没有得到覆盖率报告,因为一个覆盖了另一个。

我目前正在三叶草中生成报告,但我对其他报告非常开放。

我的测试仅在 phpunit 运行时有效:

/home/y/bin/phpunit --coverage-html clover --coverage-clover clover/report.xml --include-path src/  tests/aTest.php
OK (1 test, 1 assertions)
/home/y/bin/phpunit --coverage-html clover --coverage-clover clover/report.xml --include-path src/  tests/bTest.php
OK (1 test, 1 assertions)
/home/y/bin/phpunit --coverage-html clover --coverage-clover clover/report.xml --include-path src/  tests/cTest.php
OK (1 test, 1 assertions)

但这会导致每次运行都擦除前一次报告。所以我只得到最后一个的报告。如果我尝试按照 phpunit 期望生成完整报告的方式运行它们,我就会失败,因为我的所有类都包含自己的静态类。

/home/y/bin/phpunit --coverage-html clover --coverage-clover clover/report.xml --include-path src/  tests/
. (first test pass)
PHP Fatal error:  Cannot redeclare class Something
make[1]: *** [phpunit_run] Error 255

(但即使使用--process-isolation --no-globals-backup上述内容也会失败,因为这不是它们的意思...... -- 这不是关于如何在 php 单元上正确获得进程隔离的另一个问题。 我可以运行几次,我只想:)获得完整的覆盖报告

有没有办法让测试像第一个代码块一样正确运行(即在多个进程上以避免污染的全局类声明空间),但仍然具有全面的代码覆盖率报告?

谢谢!

Schleis 的回答对我不起作用。在我的情况下,unserialize() 方法抛出了一个错误:偏移错误...

但是,有一种非常简单的方法可以实现此目的:

按照此处所述下载 phpcov 。

让 phpunit 生成 php 覆盖率报告:

phpunit --coverage-php coverage/cov/foo.cov tests/foo
phpunit --coverage-php coverage/cov/bar.cov tests/bar

现在你有 2 个 .cov 文件。然后在你最喜欢的外壳中:

phpcov merge --clover clover.xml /coverage/cov

它将生成一个三叶草.xml报告文件。

您必须编写解决方案的脚本,我不知道让 phpunit 将其他运行的覆盖范围加在一起的选项。 但是phpunit代码使这不会太痛苦。

您需要使用--coverage-php选项来获取覆盖范围报告。 这将使使用 php 脚本将它们组合在一起变得更加容易。 此选项输出包含序列化PHP_CodeCoverage对象的文件。 此对象具有可用于合并报表的方法merge。 然后,可以使用相应类型的报表对象为您生成输出。

https://github.com/sebastianbergmann/php-code-coverage/tree/master/src/CodeCoverage/Report

由于现在用于分发 PHPUnit 的 .phar 文件,我在包含 PHPUnit 对象时确实遇到了问题。 您可能需要考虑将此 .gist 用于您自己的自动包含。

您的脚本将如下所示:

$fileList = ['file1', 'file2', 'file3']; //or read from dir, however you get the list.
$coverageReports = [];
foreach($fileList as $file) {
    $coverageReports[] = unserialize(file_get_contents($file));
}
$mainReport = new PHP_CodeCoverage(); //Could also use one of the other ones that were generated.
foreach($coverageReports as $coverageReport) {
    $mainReport->merge($coverageReport);
}
//Change this object depending on the format you want.
$htmlReport = new PHP_CodeCoverage_Report_HTML();  
$htmlReport->process($mainReport);