Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHPUnit Strict Mode - setUp() - Coverage

Tags:

php

phpunit

I currently started using the strict-Mode in PHPUnit, when I came across a Problem with the code-coverage:

If I use the setUp-method to create a new instance of a my class the __constructor-method is listed in the code-coverage as covered when i run the tests.

This is my test-setup:

phpunit.config.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd"
    bootstrap="../vendor/autoload.php"
    backupGlobals="false"
    backupStaticAttributes="false"
    colors="true"
    verbose="true"    
    beStrictAboutOutputDuringTests="true"
    beStrictAboutTestSize="true"
    beStrictAboutTestsThatDoNotTestAnything="true"
    beStrictAboutTodoAnnotatedTests="true"

    checkForUnintentionallyCoveredCode="true"
    processIsolation="false"
>
<testsuites>
    <testsuite name="FooTests">
        <directory suffix="Test.php">../tests</directory>
    </testsuite>
</testsuites>
<filter>
    <whitelist>
        <directory suffix=".php">../src</directory>
    </whitelist>
</filter>
<logging>
    <log type="coverage-html" target="coverage/" higlight="true" showUncoveredFiles="true"></log>    
</logging>

Foo.php

class Foo
{

    protected $_bar;

    public function __construct($bar)
    {
        $this->_bar=$bar;             //Line 10
    }                                 //Line 11

    public function getBar()
    {
        return $this->_bar;
    }

    public function getBar2()
    {
        return $this->_bar;
    }

}

and the Test: FooTest.php

class FooTest extends \PHPUnit_Framework_TestCase
{

    protected $_foo;

    protected function setUp()
    {
        $this->_foo=new Foo(10);
    }

    public function testGetBar()
    {
        $this->assertSame(10, $this->_foo->getBar());
    }

    /**
     * @covers Foo::getBar2
     */
    public function testGetBar2()
    {
        $this->assertSame(10, $this->_foo->getBar2());
    }

}

If I run the tests I get this result:

PHPUnit 4.5.0 by Sebastian Bergmann and contributors.

Configuration read from C:\xampp\htdocs\unittest\build\phpunit.config.xml

.R

Time: 88 ms, Memory: 3.50Mb

There was 1 risky test:
1) FooTest::testGetBar2
This test executed code that is not listed as code to be covered or used:
- C:\xampp\htdocs\unittest\src\Foo.php:10
- C:\xampp\htdocs\unittest\src\Foo.php:11

OK, but incomplete, skipped, or risky tests!
Tests: 2, Assertions: 2, Risky: 1.

Generating code coverage report in HTML format ... done

As soon as I specify the @covers on the test the problem appears.

Is this expected behavior?

Some things I tried:

  • Changing checkForUnintentionallyCoveredCode to false obviously works, but I want to use this feature...
  • Using processIsolation="true" works too. I don't know why?
  • Adding @covers or @uses to setUp() doesn't work
  • Adding @covers that the setUp() uses to the test does work, but the test doesn't actually cover the code. (If the tests get more complex, this seems to be a lot of writing...)
  • Different phpunit-Version: I tried this with 4.3 and 4.5 with same results
  • Different PHP-Setup: I tried this on a Win8 with XAMPP and a LinuxMint - same results

Is there a way to remove the setUp() code from the code-coverage and using @covers on tests with methods they actually test?

Edit: This also affects inheritance. So if Bar extends Foo, and passes arguments on to Foo::__construct that will be on the code-coverage too - which makes writing the @covers for the __construct a pain in the a**...

Additional info:

PHP 5.6.3 (cli) (built: Nov 12 2014 17:18:08)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies
with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans
like image 666
SpazzMarticus Avatar asked Feb 19 '15 08:02

SpazzMarticus


People also ask

What is code coverage in PHPUnit?

Code Coverage Analysis. Wikipedia: In computer science, code coverage is a measure used to describe the degree to which the source code of a program is tested by a particular test suite.

What is code coverage percentage?

Code Coverage Percentage = (Number of lines of code executed by a testing algorithm/Total number of lines of code in a system component) * 100.


1 Answers

Since this question started to gain some momentum: Here is my kind-of-solution for the problem.

My unit-test (FooTest) of Foo will always use Foo, therefore I add @uses Foo to the class.

This is also important if protected/private functions are used by public functions, because else you have to add each and every protected/private function to a test, if the class uses the function internally. I even think it is wrong if you are doing unit-tests, because a unit-test must not care about how the class does "stuff", it should only assert that a specific input results in a specific output.

(Additionally: The constructor should only do assignments, nothing else.)

After adding @uses the error will disapear.

(You can add @covers Foo::_construct to the class to have code-coverage of your constructor.)

/**
 * @uses Foo 
 * (optional)@covers Foo::__construct
 */
class FooTest extends \PHPUnit_Framework_TestCase
{
    protected $_foo;

    protected function setUp()
    {
        $this->_foo=new Foo(10);
    }

    public function testGetBar()
    {
        $this->assertSame(10, $this->_foo->getBar());
    }

    /**
     * @covers Foo::getBar2
     */
    public function testGetBar2()
    {
        $this->assertSame(10, $this->_foo->getBar2());
    }
}
like image 145
SpazzMarticus Avatar answered Sep 24 '22 12:09

SpazzMarticus