Подтвердить что ты не робот

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
4b9b3361

Ответ 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.

Ответ 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