Does this make sense:
As we generally only want to test the API (of a class) and not the implementation details we generally do not need/want to test protected methods. As we do not want code coverage to drop just because we do not test implementation details we should use the @codeCoverageIgnore
annotation for those protected methods.
If One test cover more than one class method you can use the covers annotation as described in the doc here. As example:
/**
* @covers Foo::foo
* @covers Foo::bar
*/
public function testReversed()
{
$this->assertEquals(0, $this->foo->getReversedName());
}
Hope this help
Test your private and protected methods through the public API.
The rule "don't test your privates" doesn't mean you shouldn't test the behaviour provided by private methods. It means you should test that behaviour via public methods. If you do this, you'll get the flexibility of changing the implementation later (i.e. create different private methods, or inline them).
Obviously you'll be writing multiple test cases for a single method you're testing. Make sure you name those methods to clearly state what you expect. For example:
test_it_reverses_the_name()
test_it_lowercases_characters_in_the_reversed_name()
test_it_throws_an_exception_if_name_is_missing()
Notice that if you're test driving a public method you don't often start by creating private methods. You rather extract them as a refactoring step. Later you might also decide to inline those methods without the need of changing tests. That's because you were only testing the public behaviour.
There's no need to use @codeCoverageIgnore
or @covers
. You'll be lying to yourself.
Example
Foo.php
:
<?php
class Foo
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getReversedName()
{
$this->foo();
return strrev($this->name);
}
protected function foo()
{
$foo = true;
}
}
FooTest.php
:
<?php
class FooTest extends \PHPUnit_Framework_TestCase
{
public function test_it_reverses_the_name()
{
$foo = new Foo('test');
$this->assertSame('tset', $foo->getReversedName());
}
}
phpunit.xml.dist
:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-html" target="build/coverage"/>
</logging>
</phpunit>