不测试受保护方法时如何达到100%代码覆盖率

时间:2016-03-21 20:47:10

标签: php unit-testing phpunit

这是否有意义:

由于我们通常只想测试API(类)而不是实现细节,所以我们通常不需要/想要测试受保护的方法。由于我们不希望代码覆盖率因为我们不测试实现细节而丢弃,因此我们应该对这些受保护的方法使用@codeCoverageIgnore注释。

Without @codeCoverageIgnore With @codeCoverageIgnore

2 个答案:

答案 0 :(得分:6)

通过公共API测试您的私有和受保护的方法。

规则“不测试您的私有”并不意味着您不应该测试私有方法提供的行为。这意味着您应该通过公共方法测试该行为。如果这样做,您将获得以后更改实现的灵活性(即创建不同的私有方法,或者内联它们)。

显然,您将为您正在测试的单个方法编写多个测试用例。确保将这些方法命名为清楚地说明您的期望。例如:

  • test_it_reverses_the_name()
  • test_it_lowercases_characters_in_the_reversed_name()
  • test_it_throws_an_exception_if_name_is_missing()

请注意,如果您正在测试驾驶公共方法,则通常不会创建私有方法。您宁可将它们作为重构步骤提取出来。稍后您可能还决定在不需要更改测试的情况下内联这些方法。那是因为你只测试了公共行为。

无需使用@codeCoverageIgnore@covers。你会骗自己。

示例

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>

coverage

答案 1 :(得分:0)

如果一个测试涵盖多个类方法,则可以使用covers annotation as described in the doc here。例如:

/**
 * @covers Foo::foo
 * @covers Foo::bar
 */
public function testReversed()
{
    $this->assertEquals(0, $this->foo->getReversedName());
}

希望这个帮助