View Issue Details

IDProjectCategoryView StatusLast Update
0001798XdebugCode Coveragepublic2021-04-08 09:50
Reporterdvdoug Assigned Toderick  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionwon't fix 
Product Version2.9.6 
Target Version3.0dev 
Summary0001798: Inconsistent reporting of executable lines
Description

When a class implements an interface and the class is first included while code coverage is active, then the class definition line is counted as executable when coverage is retrieved the first time. But only the first time.

When the same file is included while code coverage is not active, then the class definition line is never counted as executable.

This results in inconsistent code coverage numbers depending on external factors e.g. whether PHPUnit's processUncoveredFiles mode is on or off, or whether Symfony has decided to recompile it's container before a particular run.

This does not seem to affect simple classes that do not implement an interface, there the class definition always seems to be considered non-executable. I would suggest this case is handled the same.

Steps To Reproduce

MyInterface.php
<?php

interface MyInterface
{

}

MyClass.php
<?php
require_once 'MyInterface.php';
class MyClass implements MyInterface
{
public function foo()
{
$foo = 'bar';
}
}

Test script A (file included during first call, second call gives different line numbers)
<?php
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
require_once 'MyClass.php';
print_r(xdebug_get_code_coverage());
xdebug_stop_code_coverage();

xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
$class = new MyClass();
$class->foo();
print_r(xdebug_get_code_coverage());

Test script B (file included before coverage begins)
<?php
require_once 'MyClass.php';

xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
$class = new MyClass();
$class->foo();
print_r(xdebug_get_code_coverage());

TagsNo tags attached.
Operating System
PHP Version7.4.0-7.4.4

Activities

dvdoug

2020-07-03 17:06

reporter   ~0005424

https://github.com/sebastianbergmann/php-code-coverage/issues/774 suggests this might apply to "extends" as well as "implements"

derick

2021-04-08 09:50

administrator   ~0005821

I have had a long look at this, and I think I have come to the conclusion that I do not want to address this right now.

Code coverage analyses which code can be executed when code coverage is active, and a new scope (script, method, or function) is seen for the first time. When code then runs, it modifies this information with whether code has been executed when specific lines have been hit. When code coverage was implemented, it was never meant to be stopped and started between every test, but rather, collect information for the whole execution as all the tests in one go. This means that it is now impossible to reset the internal collected information to the analysed stated (which line is executable etc). The only way would be to reanalyse everything. And that'd be so slow that nobody would ever want to do code coverage again.

The only way to solve this is to split the "analyse what code can do what" and "collect which lines/etc have been hit" into two separate internal data stores, and merge that information when returning it with xdebug_get_code_coverage(). That's going to be a major undertaking (read: months), and I don't think I will have the time for that, considering all the other issues I want to fix, and features to add.

Issue History

Date Modified Username Field Change
2020-06-14 17:28 dvdoug New Issue
2020-06-20 15:07 derick Status new => acknowledged
2020-07-03 17:06 dvdoug Note Added: 0005424
2021-03-17 08:51 derick Target Version => 3.0dev
2021-04-08 09:50 derick Assigned To => derick
2021-04-08 09:50 derick Status acknowledged => resolved
2021-04-08 09:50 derick Resolution open => won't fix
2021-04-08 09:50 derick Note Added: 0005821