PHPUnit Строгий режим - setUp() - Покрытие
В настоящее время я начал использовать strict
-Mode в PHPUnit, когда я столкнулся с проблемой с охватом кода:
Если я использую метод 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;
}
}
и Test: 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
-Version: я пробовал это с помощью 4.3
и 4.5
с теми же результатами
- Различные PHP-установки: я пробовал это на Win8 с XAMPP и LinuxMint - те же результаты
Есть ли способ удалить код setUp()
из покрытия кода и использовать @covers
при тестировании методами, которые они фактически тестируют?
Изменить: это также влияет на наследование. Поэтому, если Bar
расширяет Foo
и передает аргументы на Foo::__construct
, который также будет включен в покрытие кода, что делает запись @covers
для __construct
болью в **...
Дополнительная информация:
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
Ответы
Ответ 1
Поскольку этот вопрос начал набирать определенный импульс: вот мой вид решения проблемы.
Мой unit -test (FooTest
) Foo
всегда будет использовать Foo
, поэтому я добавляю @uses Foo
в класс.
Это также важно, если функции protected
/private
используются функциями public
, потому что иначе вам нужно добавить каждую функцию protected
/private
к тесту, если класс использует функция внутренне. Я даже думаю, что это неправильно, если вы выполняете модульные тесты, потому что unit тест не должен заботиться о том, как класс "работает", он должен только утверждать, что конкретный ввод приводит к определенному результату.
(Дополнительно: конструктор должен выполнять только назначения, ничего больше.)
После добавления @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());
}
}
Ответ 2
Вы указали строгий охват checkForUnintentionallyCoveredCode="true"
. И поскольку PHPUnit 4.0 PHPUnit имеет следующее поведение:
Работа с непреднамеренно покрываемым кодом
PHPUnit 4.0 необязательно может быть строгим относительно непреднамеренно охваченного кода (строгого режима покрытия). Когда это разрешено, PHPUnit завершит тест, который использует аннотацию @covers и выполнит код, который не указан с помощью аннотации @covers.
Ответ 3
В PHPUnit> = 6.0 установите для свойства beStrictAboutCoversAnnotation значение phpunit.xml
:
<phpunit
// ....
beStrictAboutCoversAnnotation="false"
>
// ....
Кроме того, вы можете запустить phpunit без --strict-покрытие
Подробнее о Рискованных тестах: непреднамеренно скрытый код
Ответ 4
Я не думаю, что принятый ответ правильный. В основном это говорит о том, что все в этом классе можно использовать. Который может или не может быть тем, что вы хотите. В частности, если вы хотите убедиться, что ваш метод testGetBar2()
не использует какой-либо другой код, который вы не сможете использовать.
Вы можете игнорировать то, что делает ваш метод настройки.
/**
* @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