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
,问题就会出现。
这是预期的行为吗?
我试过的一些东西:
- 将
checkForUnintentionallyCoveredCode
更改为 false
显然有效,但我想使用此功能...
- 使用
processIsolation="true"
也可以。不知道为什么?
- 将
@covers
或 @uses
添加到 setUp()
不起作用
- 将
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
您已使用 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
的更多信息
我认为接受的答案不正确。它基本上表示 class 中的任何内容都可以使用。这可能是也可能不是你想要的。特别是如果你想确保你的 testGetBar2()
方法不使用其他代码,你将无法做到。
你能做的就是ignore你的设置方法的作用。
/**
* @codeCoverageIgnore
*/
protected function setUp()
{
$this->_foo=new Foo(10);
}
这样一来,您在设置中放入的任何内容都不会算作经过测试的代码,但会显示您特别涵盖的任何内容。
我目前开始在 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
,问题就会出现。
这是预期的行为吗?
我试过的一些东西:
- 将
checkForUnintentionallyCoveredCode
更改为false
显然有效,但我想使用此功能... - 使用
processIsolation="true"
也可以。不知道为什么? - 将
@covers
或@uses
添加到setUp()
不起作用 - 将
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
您已使用 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
的更多信息我认为接受的答案不正确。它基本上表示 class 中的任何内容都可以使用。这可能是也可能不是你想要的。特别是如果你想确保你的 testGetBar2()
方法不使用其他代码,你将无法做到。
你能做的就是ignore你的设置方法的作用。
/**
* @codeCoverageIgnore
*/
protected function setUp()
{
$this->_foo=new Foo(10);
}
这样一来,您在设置中放入的任何内容都不会算作经过测试的代码,但会显示您特别涵盖的任何内容。