Reputation: 571
I'm using PHPUnit 3.5.14 and have a suite of tests which covers 100% of my PHP application excluding certain portions with // @codeCoverageIgnore[Start|End]. The HTML coverage report shows 100% coverage. But when I generate a Clover XML coverage report, which I'd like Jenkins to read to enforce the 100% coverage requirement, it shows all of my ignored code as not covered.
For example, I have a controller class with 20 methods, one of which looks like this:
// @codeCoverageIgnoreStart
/**
* Gets an instance of Foo. Abstracted for testing.
*
* @param array $options The constructor argument
*
* @return Foo
*/
protected function _getFoo(array $options)
{
return new Foo($options);
}
// @codeCoverageIgnoreEnd
The HTML coverage report shows 20 methods covered including the one entirely ignored:
pic: coverage report excerpt
https://i.sstatic.net/AvpN5.png
But the Clover XML report shows 19/20 methods covered and doesn't mention _getFoo:
<class name="CampaignController" namespace="global" (...)>
<metrics methods="20" coveredmethods="19" conditionals="0" coveredconditionals="0" statements="532" coveredstatements="532" elements="552" coveredelements="551"/>
...
<line num="592" type="stmt" count="1"/>
<line num="593" type="stmt" count="1"/>
<line num="615" type="method" name="createAction" crap="2" count="2"/>
<line num="617" type="stmt" count="2"/>
(The _getFoo lines at the top are lines 596-608.)
The logging section of my PHPUnit configuration looks like this:
<logging>
<log type="coverage-html" target="../public/build/coverage" charset="UTF-8"
yui="true" highlight="true" lowUpperBound="90" highLowerBound="100"/>
<log type="coverage-clover" target="../public/build/test-coverage.xml"/>
</logging>
Is there a way to configure the Clover coverage log entry, or change my coverage ignore comments, so that the Clover report indicates 100% coverage to match the HTML report?
Upvotes: 3
Views: 2994
Reputation: 36532
The problem lies in PHP_CodeCoverage_Report_Clover::process()
. While it correctly ignores marked lines while adding up the number of lines in a method, it gets the list of methods from PHP_Token_Stream
which doesn't know about those code coverage comments. I created issue #54 at github which should be relatively easy to fix.
BTW, reading PHP_CodeCoverage::getLinesToBeIgnored()
which PHP_CodeCoverage_Report_Clover
uses, it appears that you can ignore an entire class or method by adding @codeCoverageIgnore
to its docblock.
/**
* Gets an instance of Foo. Abstracted for testing.
*
* @param array $options The constructor argument
* @return Foo
*
* @codeCoverageIgnore
*/
While this won't solve the problem, it is easier than using matching //
comments.
Update: If you want to try out a fix, replace the foreach
loop over the methods inside PHP_CodeCoverage_Report_Clover::process()
with this modified version.
foreach ($_class['methods'] as $methodName => $method) {
$methodCount = 0;
$methodLines = 0;
$methodLinesCovered = 0;
for ($i = $method['startLine'];
$i <= $method['endLine'];
$i++) {
if (isset($ignoredLines[$i])) {
continue;
}
$add = TRUE;
$count = 0;
if (isset($files[$filename][$i])) {
if ($files[$filename][$i] != -2) {
$classStatistics['statements']++;
$methodLines++;
}
if (is_array($files[$filename][$i])) {
$classStatistics['coveredStatements']++;
$methodLinesCovered++;
$count = count($files[$filename][$i]);
}
else if ($files[$filename][$i] == -2) {
$add = FALSE;
}
} else {
$add = FALSE;
}
$methodCount = max($methodCount, $count);
if ($add) {
$lines[$i] = array(
'count' => $count,
'type' => 'stmt'
);
}
}
if ($methodLines > 0) {
$classStatistics['methods']++;
if ($methodCount > 0) {
$classStatistics['coveredMethods']++;
}
$lines[$method['startLine']] = array(
'count' => $methodCount,
'crap' => PHP_CodeCoverage_Util::crap(
$method['ccn'],
PHP_CodeCoverage_Util::percent(
$methodLinesCovered,
$methodLines
)
),
'type' => 'method',
'name' => $methodName
);
}
}
Upvotes: 2