Reputation: 191
I am trying to generate an HTML Code Coverage report for a running PHP application. My goal is profile the application with XDebug while I run my functional tests to determine the code coverage of my functional test suite.
I can measure the code coverage for my unit tests via phpunit (which uses the php-code-coverage API to profile each unit test individually, then aggregates it into a code coverage report). And because these tools are built on top of xdebug I'm hoping that there is a way to take the output file from the XDebug profiler and generate an HTML report.
Here's what I have so far:
I am able to generate a cachegrind.out file by adding the following configuration in php.ini:
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
Then running my functional tests with the XDebug Helper Chrome extension in "PROFILE" mode. This adds XDEBUG_PROFILE to the cookie field of the HTTP requests which in turn triggers the profiler in the PHP application. (Alternatively, you could just turn on the profiler on for all requests with xdebug.profiler_enable=1)
The problem I have is transforming the output file (cachegrind.out) into the same kind of html report that is provided by phpunit. I can the profiler output using kcachegrind, but that application doesn't have a way to export a code coverage report, let alone specify included/excluded files.
I've also looked into the phpcov command line tool, but while it supports serialized PHP_CodeCoverage objects, it doesn't work with XDebug cachegrind files.
I am hoping that I can write some PHP that imports the XDebug profiler output file (cachegrind.out) into a PHP_CodeCoverage object and then following the example in the PHPUnit source code to make an HTML report. Does anyone have any experience profiling a running PHP application in this way? Is there an easier way to go about doing it?
I'd like to avoid using the PHP_CodeCoverage directly in my PHP application source code if possible.
Upvotes: 1
Views: 3383
Reputation: 191
I ended up doing this with the PHP Code Coverage library. I created an object and started tracking code coverage in the pre_system CodeIgniter hook and wrote the coverage report to a file in the post_system CodeIgniter hook. Then I made a script to merge the coverage-php objects and output them as HTML.
I had thought merging the HTML files would be possible with phpcov, but I couldn't merge .html reports because of a missing "Template" file. I also was surprised to find that phpcov doesn't allow you to specify the output format for merged files (i.e. I could merge .cov files but couldn't output them to a .html report).
So here's my merge code, mostly just an extension of this post, but his method for unserializing .cov files didn't work for me in 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";
Upvotes: 1
Reputation: 8326
You cannot get fine-grained code coverage data from an analysis of profiling data. The latter only has the information that a function or method has been executed. While that is sufficient to calculate a weak variant of function coverage and method coverage it is not enough to yield fine-grained line coverage, for instance.
Upvotes: 1