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%, что нормально:
И, наконец, если я введу вторую из команд, команда "B" скажет DummyBCommand
Я до сих пор вижу, что ни configure()
ни execute()
методы были рассмотрены, и я вижу, как и ожидалось, красную область на каждом из этих методов:
До здесь все работает как положено.
Шаг 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]
Вот:
Так что по какой-то причине... тестирование 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 года (или, по крайней мере, та, которую мастер обновления предложил мне установить).
Итак... скачать, настроить, скомпилировать, установить и бум, готово!