PHPUnit 严格模式 - setUp() - 覆盖率

PHPUnit Strict Mode - setUp() - Coverage

我目前开始在 PHP 单元中使用 strict 模式,当时我遇到了代码覆盖问题:

如果我使用 setUp-方法创建我的 class 的新实例,__constructor-方法列在代码覆盖范围内,当我 运行 测试。

这是我的测试设置:

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;
    }

}

和测试: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());
    }

}

如果我 运行 测试我得到这个结果:

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

只要我在测试中指定 @covers,问题就会出现。

这是预期的行为吗?

我试过的一些东西:

有没有办法从代码覆盖范围中删除 setUp() 代码并在测试中使用 @covers 他们实际测试的方法?

编辑:这也会影响继承。因此,如果 Bar 扩展 Foo,并将参数传递给 Foo::__construct,这也将在代码覆盖范围内——这使得为 __construct 编写 @covers **痛...

附加信息:

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

您已使用 checkForUnintentionallyCoveredCode="true" 指定严格覆盖。由于 PHPUnit 4.0 PHPUnit 具有以下行为:

Dealing with unintentionally covered code

PHPUnit 4.0 can optionally be strict about unintentionally covered code (strict > coverage mode). When enabled, PHPUnit will fail a test that uses the @covers annotation and executes code that is not specified using a @covers annotation.

由于这个问题开始获得一些动力:这是我对这个问题的一种解决方案。

我的单元-Foo的测试(FooTest)将始终使用Foo , 因此我将 @uses Foo 添加到 class.

如果 protected/private 函数被 public 函数使用,这也很重要,因为否则你必须添加每个 protected/private 函数进行测试,如果 class 在内部使用该函数。我什至认为如果你在做单元测试是错误的,因为单元测试不应该关心 class 如何做 "stuff",它应该只断言特定的输入导致特定的输出.

(另外:构造函数应该只做赋值,没有别的。)

添加 @uses 后错误将消失。

(您可以将 @covers Foo::_construct 添加到 class 以获得构造函数的代码覆盖率。)

/**
 * @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());
    }
}

PHPUnit >= 6.0 上将 beStrictAboutCoversAnnotation 设置为 false phpunit.xml:

<phpunit
     // ....     
     beStrictAboutCoversAnnotation="false"
>
// ....

另外,你可以 运行 phpunit 没有 --strict-coverage

有关 Risky Tests: Unintentionally Covered Code

的更多信息

我认为接受的答案不正确。它基本上表示 class 中的任何内容都可以使用。这可能是也可能不是你想要的。特别是如果你想确保你的 testGetBar2() 方法不使用其他代码,你将无法做到。

你能做的就是ignore你的设置方法的作用。

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

这样一来,您在设置中放入的任何内容都不会算作经过测试的代码,但会显示您特别涵盖的任何内容。

https://phpunit.de/manual/3.7/en/code-coverage-analysis.html#code-coverage-analysis.ignoring-code-blocks