PHPUnit严格模式 - setUp() - 覆盖范围

时间:2015-02-19 08:54:04

标签: php phpunit

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

如果我使用setUp - 方法创建我的类的新实例,__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,就会出现问题。

这是预期的行为吗?

我尝试过的一些事情:

  • checkForUnintentionallyCoveredCode更改为false显然有效,但我想使用此功能......
  • 使用processIsolation="true"也可以。我不知道为什么?
  • @covers@uses添加到setUp()不起作用
  • 添加@covers用于测试的setUp()确实有效,但测试实际上并不涵盖代码。 (如果测试变得更复杂,这似乎是很多写作......)
  • 不同phpunit - 版本:我使用4.34.5尝试了相同的结果
  • 不同的PHP-Setup:我在带有XAMPP和LinuxMint的Win8上试过这个 - 结果相同

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

编辑:这也会影响继承。因此,如果Bar扩展Foo,并将参数传递给代码覆盖范围内的Foo::__construct,那么就会为@covers编写__construct a **中的痛苦......

其他信息:

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

4 个答案:

答案 0 :(得分:4)

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

Foo单元 - 测试(Foo)始终使用 @uses Foo,因此我添加了protected到了班级。

如果private函数使用public / protected函数,这也很重要,因为否则您必须添加每个private / {{ 1}}函数测试,如果类在内部使用该函数。我甚至认为如果你进行单元测试是错误的,因为单元测试一定不关心类如何做“东西”,它应该只断言特定输入会产生特定的输出。 < / p>

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

添加@uses后,错误将会消失。

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

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

答案 1 :(得分:2)

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

  

处理无意中涵盖的代码

     

PHPUnit 4.0可以选择严格关于无意中覆盖的代码(严格的&gt;覆盖模式)。启用后,PHPUnit将使用@covers注释的测试失败,并执行未使用@covers注释指定的代码。

答案 2 :(得分:0)

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

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

此外,您可以在不使用--strict-coverage的情况下运行phpunit

有关Risky Tests: Unintentionally Covered Code的更多信息

答案 3 :(得分:0)

我认为接受的答案不正确。它基本上说,该类中的任何内容都可以使用。可能是您想要的,也可能不是。具体来说,如果您要确保您的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