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

mos*_*ted 3 php phpunit unit-testing

这有意义吗:

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

没有@codeCoverageIgnore 使用@codeCoverageIgnore

Jak*_*las 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

覆盖

  • 另外,我注意到你的私有方法只为一个局部变量赋值.计算覆盖率的方式有问题,有时不包括结束括号.因为你只有一个线路方法可能会出现问题.如果覆盖范围发生任何变化,请尝试从这些方法返回进行验证. (2认同)