PhpUnit + Symfony: почему покрытие показывает белый цвет вместо красного и дает 100% на непроверенном классе?

У меня проблема, и я создал пустой проект, чтобы воспроизвести минимальную ситуацию, которая делает его повторяемым.

проблема

Проект с непроверенными классами дает 100% охват. Проблемные методы не вызваны косвенно откуда-то еще. Хотя существуют другие методы непроверенного класса, которые косвенно вызываются при тестировании другого класса.

Как воспроизвести

Шаг 1: Создайте новый пустой проект Symfony.

  • Я создал новый проект Symfony 3.3 с этой командой: symfony new coverage_trial_to_be_deleted

Результат: если я бегу vendor/bin/simple-phpunit --coverage-html coverageReport Как и ожидалось, я получил полностью протестированный проект, так как образец содержит один тест по умолчанию для одного контроллера по умолчанию.

Шаг 2: Удалите контроллер и создайте две команды, но не закрывайте их.

  • Затем я устраняю контроллер, удаляя полный src/Controller каталог, тест для контроллера и ссылки на этот директрой в конфигурации приложения.
  • Затем я создаю src/Command каталог с 2 командами: DummyACommand.php а также DummyBCommand.php,
  • Затем я создаю глупый тест, который выполняет assertTrue( true ); иметь что-то сообщить, но не вызывает команд вообще.

Результат: это работает правильно. Затем он сообщает 0% на Command каталог, как это:

Результат всего раздела Команда

В частности, внутри Command Я вижу 2 команды на 0%, что нормально:

Команды на 0

И, наконец, если я введу вторую из команд, команда "B" скажет DummyBCommandЯ до сих пор вижу, что ни configure() ни execute() методы были рассмотрены, и я вижу, как и ожидалось, красную область на каждом из этих методов:

Отчет команды B

До здесь все работает как положено.

Шаг 3: Добавить тест только для команды A и НЕ тестировать команду B.

Затем я добавляю новый тест с именем DummyACommandTest.php со следующим содержанием:

<?php

declare( strict_types=1 );

namespace Tests\AppBundle\Command;

use AppBundle\Command\DummyACommand;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

class EnvironmentListCommandTest extends KernelTestCase
{
    public function testExecute()
    {
        $kernel = $this->createKernel();
        $kernel->boot();

        $application = new Application( $kernel );
        $application->add( new DummyACommand() );

        $command = $application->find( 'dummy:a' );
        $commandTester = new CommandTester( $command );
        $commandTester->execute(
            [
                'command' => $command->getName(),
            ]
        );

        $output = $commandTester->getDisplay();
        $this->assertContains( 'dummy A command', $output );
    }
}

Тест дает зеленый свет, как и ожидалось, так как он вызывает DummyACommand и выполняет его, затем проверяет вывод и действительно содержит то, что ожидается:

Тесты проходят с зеленым светом

Там написано 2 теста, потому что assertTrue( true ); все еще там.

Результат: теперь, если я посмотрю на покрытие DummyBCommand, я должен увидеть configure() метод покрыт, потому что факт тестирования A вызывает $application->find( 'dummy:a' ); и я думаю, что это исследует все команды.

Я действительно не очень понимаю это, так как я делаю только $application->add( new DummyACommand() ); и я не знаю когда dummy:b загружен, но в любом случае давайте дадим этой гипотезе шанс.

Так что я не против увидеть configure() в зеленом (аннотация [1] на следующем изображении).

Но то, что мне не нравится, это то, что execute() вместо B вместо красного (никто не вызывает это выполнение, должно отображаться точно так же, как в шаге 2), оно отображается белым!!!:| как в аннотации [2] Вот:

Теперь команда 2 имеет белый раздел вместо красного

Так что по какой-то причине... тестирование Command A заставляет PHPUnit изменить свое мнение о том, что является "потенциально исполняемым" в Command B, и я не понимаю, почему.

Это делает полный проект проверенным на 100% проверенным, в то время как он ложный, как здесь:

Полный отчет показывает ложное покрытие

но, конечно, эта информация не отражает реальность: execute() Метод команды B не рассматривается и никогда не выполняется.

Я надеюсь, что в отчете будет показано 75% покрытия линии (3 из 4) и 50% покрытия класса (1 из 2).

Итак... Вопрос:

Почему PhpUnit меняет свое мнение о том, что является потенциально исполняемым кодом в классе B, при добавлении теста для класса A?

Как я могу дать PhpUnit команду увидеть B как непокрытый?

Спасибо! Хави.

1 ответ

Решение

Найденный!!

Быстрое решение

Обновите xdebug библиотека здесь: https://xdebug.org/wizard.php

Детальное решение

Как вы можете видеть на изображениях вопроса, я использовал Xdebug 2.4.0 потому что это тот, который только что был в моей системе, стабильной Ubuntu 16.04,

В соответствии с этой веткой: https://github.com/sebastianbergmann/php-code-coverage/issues/411 течение одного полного года эти люди (спасибо вам всем) преследовали одну и ту же проблему: строки не были объявлены исполняемыми.

Наконец они пришли к выводу, что в XDebug и это наконец было сообщено и исправлено.

Это: xdebug некорректно сообщал данные phpunit, поэтому phpunit использовал ошибочную гипотезу.

Я обновил здесь https://xdebug.org/wizard.php (ссылка, которую я нашел в этой теме), и я скомпилировал новый xdebug как указано.

Здесь вы можете видеть, что проект сейчас не на 100%, а на 75% в строках и на 50% в классах (как и ожидалось):

введите описание изображения здесь

Здесь вы можете видеть, что команда A сообщает о 100% (что хорошо, потому что это тот, который я тестирую), а команда B сообщает о 50% в строках и 0% в классе, как и ожидалось, так как я не писал тест для Это. Метод configure() запускается при загрузке ядра и загрузке приложения:

введите описание изображения здесь

И если мы введем в команду B (то есть: DummyBCommand) мы можем наконец увидеть, что метод execute() помечается как красный, а не белый:

введите описание изображения здесь

На этом изображении вы можете увидеть в [1] что configure() на 100% и execute() 0%, что правильно.

В [2] Вы можете увидеть цвета. execute() отмечен красным, как и ожидалось.

И, наконец, в [3] Вы можете видеть, что версия XDebug является 2.5.4последняя стабильная версия от 10 сентября 2017 года (или, по крайней мере, та, которую мастер обновления предложил мне установить).

Итак... скачать, настроить, скомпилировать, установить и бум, готово!

Другие вопросы по тегам