如何从xdebug输出生成PHP代码覆盖率报告

时间:2015-01-23 23:15:51

标签: php phpunit code-coverage xdebug

我正在尝试为正在运行的PHP应用程序生成HTML代码覆盖率报告。我的目标是使用XDebug对应用程序进行概要分析,同时运行我的功能测试来确定功能测试套件的代码覆盖率。

我可以通过phpunit(它使用php-code-coverage API分别对每个单元测试进行分析,然后将其聚合到代码覆盖率报告中)来测量单元测试的代码覆盖率。因为这些工具是在xdebug之上构建的,所以我希望有一种方法可以从XDebug探查器获取输出文件并生成HTML报告。

这是我到目前为止所拥有的:

我可以通过在php.ini中添加以下配置来生成cachegrind.out文件:

xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/var/log/xdebug_profiler
xdebug.profiler_output_name=cachegrind.out
xdebug.profiler_append=1
xdebug.coverage_enable=1

然后在“PROFILE”模式下使用XDebug Helper Chrome扩展程序运行我的功能测试。这会将XDEBUG_PROFILE添加到HTTP请求的cookie字段中,从而触发PHP应用程序中的探查器。 (或者,您可以使用xdebug.profiler_enable = 1为所有请求打开探查器)

我遇到的问题是将输出文件(cachegrind.out)转换为phpunit提供的同类html报告。我可以使用kcachegrind输出探查器,但该应用程序无法导出代码覆盖率报告,更不用说指定包含/排除的文件。

我也查看了phpcov命令行工具,但是虽然它支持序列化的PHP_CodeCoverage对象,但它不适用于XDebug cachegrind文件。

我希望我可以编写一些PHP,将XDebug探查器输出文件(cachegrind.out)导入PHP_CodeCoverage对象,然后按照PHPUnit源代码中的示例制作HTML报告。有没有人以这种方式分析正在运行的PHP应用程序?有没有更简单的方法去做呢?

如果可能的话,我想避免在我的PHP应用程序源代码中直接使用PHP_CodeCoverage。

2 个答案:

答案 0 :(得分:2)

您无法从分析数据分析中获得细粒度的代码覆盖率数据。后者仅具有已执行功能或方法的信息。虽然这足以计算功能覆盖率和方法覆盖率的弱变量,但例如,仅仅产生细粒度线覆盖是不够的。

答案 1 :(得分:1)

我最终使用PHP Code Coverage库执行此操作。我创建了一个对象并开始在pre_system CodeIgniter钩子中跟踪代码覆盖率,并将覆盖率报告写入post_system CodeIgniter钩子中的文件。然后我创建了一个脚本来合并coverage-php对象并将它们输出为HTML。

我原本以为可以使用phpcov合并HTML文件,但由于缺少“模板”文件,我无法合并.html报告。我也很惊讶地发现phpcov不允许你为合并文件指定输出格式(即我可以合并.cov文件,但无法将它们输出到.html报告中)。

所以这是我的合并代码,大多数只是一个extension of this post,但他的反序列化.cov文件的方法在PHP 5.3中对我不起作用

<?php
/**
 * "Deserializes" PHP_CodeCoverage objects from the files passed on the command line,
 * combines them into a single coverage object and creates an HTML report of the
 * combined coverage.
 */
require_once '/var/www/quickstart/vendor/autoload.php';

if ($argc <= 1) {
  die("Usage: php generate-coverage-report.php cov-file1 [cov-file2 cov-    file3...]\n");
}

foreach (array_slice($argv, 1) as $filename) {
  if (isset($codeCoverage)) {
      // Reconstruct serialized output (from .cov file such as generated from 'phpunit --coverage-php')
      $_coverage = include($filename);
      // $codeCoverage->filter()->addFilesToWhitelist($_coverage->filter()->getWhitelist());
      $codeCoverage->merge($_coverage);
      unset($_coverage);
  } else {
      $codeCoverage = include($filename);
  }
}

print "\nGenerating code coverage report in HTML format ...";

// Based on PHPUnit_TextUI_TestRunner::doRun
$writer = new PHP_CodeCoverage_Report_HTML(
  'UTF-8',
  false, // 'reportHighlight'
  35, // 'reportLowUpperBound'
  70, // 'reportHighLowerBound'
  sprintf(
    ' and <a href="http://phpunit.de/"></a>'
    //PHPUnit_Runner_Version::id()
      )
  );

$writer->process($codeCoverage, 'coverage');

print " done\n";
print "See coverage/index.html\n";