我目前开始使用 PHPUnit 中的 strict
-Mode,当时我遇到了代码覆盖率问题:
如果我使用 setUp
-方法创建 my 类的新实例,则运行测试时,__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>
福.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"
也有效。我不知道为什么? - 向
setUp()
添加@covers
或@uses
不起作用 - 将
setUp()
使用的@covers
添加到测试中确实有效,但测试实际上并未涵盖代码。(如果测试变得更加复杂,这似乎是很多写作...... - 不同的
phpunit
版本:我用4.3
和4.5
尝试了这个,结果相同 - 不同的PHP设置:我在带有XAMPP和LinuxMint的Win8上尝试了这个 - 相同的结果
有没有办法从代码覆盖率中删除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
由于这个问题开始获得一些动力:这是我对这个问题的解决方案。
我的单元测试(FooTest
(Foo
将始终使用Foo
,因此我在类中添加了@uses Foo
。
如果public
函数使用 protected
/private
函数,这一点也很重要,因为否则您必须将每个 protected
/private
函数添加到测试中,如果类在内部使用该函数。我什至认为如果你在做单元测试是错误的,因为单元测试一定不关心类如何做"东西",它应该只断言特定的输入导致特定的输出。
(另外:构造函数只应执行赋值,而不执行其他
任何操作。添加@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());
}
}
您已指定了 checkForUnintentionallyCoveredCode="true"
的严格覆盖范围。由于 PHPUnit 4.0 PHPUnit 具有以下行为:
处理无意中覆盖的代码
PHPUnit 4.0 可以选择对无意中覆盖的代码严格(严格>覆盖模式(。启用后,PHPUnit 将无法通过使用@covers注释并执行未使用@covers注释指定的代码的测试。
在 PHPUnit>= 6.0 上,将 beStrictAboutCoversAnnotation 设置为 false phpunit.xml
:
<phpunit
// ....
beStrictAboutCoversAnnotation="false"
>
// ....
此外,你可以在没有 --strict-coverage 的情况下运行 phpunit
有关风险测试的详细信息:无意中涵盖的代码