PCOV — это драйвер для PHP используемый в PHPUnit для code coverage, аналогичный Xdebug или PHPDBG. С помощью него можно собрать информацию о покрытых линиях кода (code coverage lines) во время тестирования.
Основным его преимуществом перед другими инструментами анализа покрытия кода является его скорость. Он работает быстрее и использует меньше ресурсов.
.wpj-jtoc.—jtoc-theme-basic-light.—jtoc-has-custom-styles {
—jtoc-numeration-suffix: «. «;
—jtoc-numeration-color: #adadad;
}
О PCOV
PCOV был создан Joe Watkins исключительно нацеленным на функциональность покрытия кода без дополнительных функций (профилирование, трассирование), присутствующих в других инструментах, таких как Xdebug и PHPDBG. Такой подход позволяет повысить производительность и ускорить тестирование.
Сравнение PCOV и Xdebug
PCOV и Xdebug — это два различных PHP инструмента, используемые преимущественно для разных задач. Однако, оба инструмента могут быть использованы для анализа покрытия кода при проведении тестирования через PHPUnit.
С PCOV мы можем собрать информацию про line coverage, тогда как с Xdebug нам доступно line, branch и path coverage. Подробнее про виды покрытия по ссылке.
PCOV обладает рядом преимуществ перед Xdebug:
- Быстрее при Code Coverage в 2-4 раза.
- Потребляет меньше ресурсов.
Из недостатков PCOV перед Xdebug можно выделить следующее:
- Не поддерживет path coverage и branch coverage.
Влияние на производительность
PCOV при включенном состоянии влияет на производительность PHP. Влияние на производительность не такое заметное как у Xdebug, но при выполнении статического анализа или запуска линтера, вы с этим можете столкнуться.
Активируйте его только для code coverage в GitHub workflow с запуском тестов или во время выполнения Code Coverage.Для активации PCOV перед запуском тестов, можно использовать следующую команду:
php -dpcov.enabled=1 -dpcov.directory=/var/www/html ./vendor/bin/phpunit --coverage-text
UPD: Ошибки в PHPUnit в режиме Code Coverage ниже 9.5.20 версии при использовании @runInSeparateProcess
При использовании PHPUnit версии ниже
9.5.20
в режиме Code Coverage с PCOV, если вы запустите PCOV непосредственно перед запуском Code Coverage, вы можете столкнуться с ошибками в тестах которые используют аннотацию@runInSeparateProcess
(что означает запустить тест в отдельном процессе):PHP Fatal error: Uncaught SebastianBergmannCodeCoverageNoCodeCoverageDriverAvailableException: No code coverage driver available in /var/www/html/vendor/phpunit/php-code-coverage/src/Driver/Selector.php:53 Stack trace: #0 Standard input code(423): SebastianBergmannCodeCoverageDriverSelector->forLineCoverage(Object(SebastianBergmannCodeCoverageFilter)) #1 Standard input code(1192): __phpunit_run_isolated_test() #2 {main} thrown in /var/www/html/vendor/phpunit/php-code-coverage/src/Driver/Selector.php on line 53 Fatal error: Uncaught SebastianBergmannCodeCoverageNoCodeCoverageDriverAvailableException: No code coverage driver available in /var/www/html/vendor/phpunit/php-code-coverage/src/Driver/Selector.php:53 Stack trace: #0 Standard input code(423): SebastianBergmannCodeCoverageDriverSelector->forLineCoverage(Object(SebastianBergmannCodeCoverageFilter)) #1 Standard input code(1192): __phpunit_run_isolated_test() #2 {main} thrown in /var/www/html/vendor/phpunit/php-code-coverage/src/Driver/Selector.php on line 53Эта ошибка говорит нам, что драйвер Code Coverage отсутстсует и пакет
phpunit/php-code-coverage
его не видит при запуске изолированного теста.Встает вопрос: Почему PHPUnit не видит драйвер? ведь мы активируем его непосредственно перед запуском Code Coverage.
Ответ заключается в том, что в PHPUnit до
9.5.20
версии, флаги с которыми запускался PHP скрипт, не передавались дочерним процессам порожденным PHPUnit Code Coverage. А значит дочерние процессы запускаются с отключенным PCOV драйвером. Подробно вы можете ознакомиться с issue на GitHub.Есть два решения:
- Обновить PHPUnit до
9.5.20
, чтобы он включал обновленную версию Code Coverage пакета с исправленной проблемой.- Если вы не можете по каким-то причинам обновиться до
9.5.20
, то необходимо активировать PCOV вphp.ini
для всего сервера в котором вы запускаете Code Coverage.
Совместимость
PCOV и Xdebug перегружают одни и те же части движка PHP, в результате чего они не совместимы для работы вместе.
Если вам будет необхоимо использовать Xdebug для дебага или профилирования, тогда будет нужно отключить PCOV и наоборот.
Про тестовый стенд
Для тестов я использовал Laravel проект BookStack. Тестовый набор проекта имеет 950 tests, 4578 assertions
и включает UnitTests и IntegrationTests. Этого набора более чем достаточно чтобы увидеть разницу в производительности между PCOV и Xdebug.
Все тесты проводились в GitHub Actions. BookStack уже содержит в себе настроенный изолированный workflow для тестов. От теста к тесту я менял coverage драйвер и версию PHP в настройках shivammathur/setup-php@v2
GitHub Action.
Каждый тест был выполнен 3 раза и для статьи были выбраны средние значения.
Время выполнения тестов приведено в минутах.
В тестах использовалась PCOV версии 1.0 на PHP 8.2 и 7.4
Коммит на котором проводились тесты
6e6f1133
Тест производительности на PHP 8.2
Давайте посмотрим на разницу в скорости и потребляемых ресурсах между PCOV и Xdebug на PHP 8.2.
PCOV
Во время тестов я получил следующие результаты
Time: 02:00, Memory: 184.50 MB
2 минтуы — довольно неплохо для 950 tests и 4578 asserts
.
Xdebug 3.2
Xdebug 3.2 был неплохо оптимизирован для снижения накладных расходов. Но время скорости выполнения у Xdebug получилость в 2 раза хуже чем у PCOV. Отличие в потреблении memory ~2mb что является незначительным показателем.
Time: 03:55, Memory: 186.50 MB
Тест производительности на PHP 7.4
PHP 7.4 не поддерживается с 28 ноября 2022, но есть множество проектов которые еще не мигрировали на 8+ версии и для этих проектов следующие тесты могут быть полезны.
PCOV
В тестах на PHP 7.4 он показал тоже самое время выполнения как и на PHP 8.2, но значения потребления memory в 2 раза выше чем на PHP 8.2.
Отличие в потреблении memory в тестах производительности для PHP 7.4 связано с оптимизациями которые были проведены в PHP 8.* версих.
Time: 02:00, Memory: 347.00 MB
Xdebug 3.1
Xdebug 3.1 по сравнению с PCOV оказался в 2.5 раза медленее на PHP 7.4. Разница в memory опять незначительная ~6mb.
Time: 04:56, Memory: 353.00 MB
Xdebug 2.9
Конечно я не рекомендую вам использовать Xdebug 2 версии, т.к. он очень медленный. Но давайте посмотрим какие результаты будут, в случае если вы все еще используете такую версию.
Тесты показали результат что Xdebug 2.9 в 4 раза медленее по сравнению с PCOV для PHP 7.4.
Time: 07:59, Memory: 355.00 MB
Итог тестов
Итоговая таблица тестов по Code Coverage:
Code Coverage Driver | PHP | Time | Memory |
PCOV | 8.2 | 02:00 | 184.50 MB |
PCOV | 7.4 | 02:00 | 347.00 MB |
Xdebug 3.2 | 8.2 | 03:56 | 186.50 MB |
Xdebug 3.1 | 7.4 | 04:56 | 353.00 MB |
Xdebug 2.9 | 7.4 | 07:59 | 355.00 MB |
Как вы можете видеть:
- PCOV быстрее Xdebug 3.2 (PHP 8.2) на 197%
- PCOV быстрее Xdebug 3.1 (PHP 7.4) на 247%
- PCOV быстрее Xdebug 2.9 (PHP 7.4) на 400%
- Xdebug 3.2 (PHP 8.2) быстрее Xdebug 3.1 (PHP 7.4) на 25%
- Xdebug 3.1 быстрее Xdebug 2.9 (PHP 7.4) на 60%
Заключение
PCOV выигрывает у Xdebug в скорости выполнения тестов с code coverage в 2-4 раза. Это может быть несущественным показателем если вы используете unit tests время выполнения которых занимает считанные секунды.
Но что если ваш проект имеет так-же интеграционные тесты с набором 5000 tests, 40000 assertions
, время выполнения которых занимает от 5 минут?
В этом случае разница в скорости в 2-4 раза между PCOV и Xdebug может быть существенной и это может повлиять на скорость CI/CD и частоту запуска тестов программистом а следовательно и на скорость разработки новых фич из-за фикса багов на позднем этапе.
Важно так-же помнить что PCOV как и Xdebug может влиять на производительность приложения. Активируйте его только для code coverage в тестовом GitHub workflow или непосредственно перед выполнением тестов.
Источник: WP-Yoda.com