Search code examples
phpphpunitphp-code-coverage

PHPUnit code coverage reports false positive inside foreach


PHPUnit code coverage is reporting 100% coverage for the following function which is clearly wrong:

public function run(){
    foreach ([1] as $value) {                    
        if($value === 1 ){
            echo "Is called\n";             // TRUE positive
        }
        else{
            echo "Not called\n";            // TRUE negative
            echo "Not called either\n";     // FALSE positive
        }
    }
}

The last line echo "Not called either" is not run, but the report says it is!

If I refactor the body of the foreach loop into another function the report becomes correct:

public function run(){
    foreach ([1] as $value) {                    
        $this->run2($value);
    }
}

public function run2($value){
    if($value === 1 ){
        echo "Is called\n";             // TRUE positive
    }
    else{
        echo "Not called\n";            // TRUE negative
        echo "Not called either\n";     // TRUE negative
    }
}

Tested with php-code-coverage 6.0.7 using PHP 7.2.10-0ubuntu0.18.04.1 with Xdebug 2.6.0 and PHPUnit 7.3.2

I've tried a few older versions of phpunit and get the same results.

Is this a bug or am I missing something here?


Solution

  • This is caused by a currently unresolved bug in PHP as described here and here.

    The problem can avoided by using a standard for loop instead of a foreach loop. Or, by moving the foreach body into another function as described in the question.