dn Fer dn Fer - 2 months ago 17
PHP Question

PHP function not reported as completely covered by PHPUnit when calling multiple times

Can someone explain why below function is not reported as completely covered by phpUnit?
Or better yet, explain how to get it reported as completely covered?

function itDoesThingsToValue()
{
static $value = -1;
if ($value < 0) {
$value = 1978;
//Do some more stuff with $value
//But $value keeps being > 0
}
return $value;
}


XDebug code coverage reports all the lines as covered when calling this function once or multiple times.

PHPUnit reports the lines as covered when calling it once.

Calling it multiple times (because of different PHPUnit tests), PHPUnit reports the lines inbetween the {} as not covered.

I know the lines between the {} execute only once because of the static variable $value, but imho executed lines should always be reported as covered, regardless if they where skipped at following calls (by following tests).

Answer

It's still not entirely clear to me, because I don't know the ins and outs of PHPUnit, but this is the case...

The function is called when my class's constructor is called during the first unit test. In this test I declare the function is covered (with @covers annotation).

Somewhere further along, I call this function again in a dataprovider to test another function.

As I thought my function was already tested and covered (within the constructor test), it should be save to use it in the dataprovider. Actually this causes the lines being reported as not covered.

So my best guess is dataprovider functions run before the unit tests do.

EDIT:

After adding some debug code, it is indeed confirmed all data provider methods are executed before any test* methods.

The following example produces my problem:

public function setUp() {
    //Echo the executed testmethod name and 'starting' time into the console.
    echo $this->getName(), ' ', date('H:i:s'), chr(10), chr(13);
}

/**
* @covers MyClass::_construct
* @covers MyClass::myMethod
*/
public function testConstructor() {
    //Do some stuff
}

public function myDataProvider() {
    //Echo the 'starting' time of the data provider method in the console.
    echo 'DataProvider started executing at', ' ', date(H:i:s), chr(10), chr(13);
    $value = MyClass::myMethod; //This causes the lines not being covered
    return [[$value + 1], [$value -1]];
}

/**
* @covers MyClass::AnotherMethod
* @dataprovider myDataProvider
*/
public function testSomethingElse {
    //Do some stuff
}

Console Output:

Testing started at 21:55 ...
DataProvider started executing at 21:55:46
PHPUnit 5.5.5 by Sebastian Bergmann and contributors.

testConstructor 21:55:47
testSomethingElse 21:55:47

My solution is:

private $testClassValue;

/**
* @covers MyClass::_construct
* @covers MyClass::myMethod
*/
public function testConstructor() {
    //Do some stuff
    $this->$testClassValue = myClass::value;
}

public function myDataProvider() {
    $value = $this->$testClassValue;
    return [[$value + 1], [$value -1]];
}

/**
* @covers MyClass::AnotherMethod
* @dataprovider myDataProvider
*/
public function testSomethingElse {
    //Do some stuff
}