В больших проектах сложно с ходу определить, какой код протестирован, а какой — нет. Такая потребность возникает регулярно. Обычно это происходит, когда не все члены команды ответственно подходят к написанию тестов. В таком случае может страдать качество проекта.
Протестированность кода можно измерить. Для этого используют метрику покрытие кода тестами (code coverage). Покрытие анализируется тестовыми фреймворками, которые берут количество строчек, задействованных в тестах, и делят их на количество строчек в проекте. Например, если в коде есть условная конструкция, не покрытая тестами, то все строки кода внутри нее не будут покрыты.
Для работы покрытия в PHPUnit необходимо установить расширение xdebug. Проще всего его установить через командную строку:
# https://pecl.php.net/
pecl install xdebug
Чтобы убедиться, что xdebug работает, запустим команду php -v
. Она покажет версию PHP и расширения:
PHP 8.2.10 (cli) (built: Sep 21 2023 01:09:05) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.10, Copyright (c) Zend Technologies
with Xdebug v3.2.2, Copyright (c) 2002-2023, by Derick Rethans
В PHPUnit покрытие меряется крайне просто. Достаточно запустить тесты с флагом --coverage-text
:
# Пример пакета https://GitHub.com/hexlet-boilerplates/php-package
cd php-package
# Чтобы посчитать процент покрытия, нужно задать нужную переменную для xdebug
XDEBUG_MODE=coverage composer exec --verbose phpunit tests -- --coverage-text
> __exec_command: phpunit 'tests' '--coverage-text'
PHPUnit 9.5.26 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:00.104, Memory: 10.00 MB
OK (1 test, 2 assertions)
Code Coverage Report:
2023-10-26 10:46:03
Summary:
Classes: 100.00% (1/1)
Methods: 100.00% (3/3)
Lines: 100.00% (4/4)
Php\Package\User
Methods: 100.00% ( 3/ 3) Lines: 100.00% ( 4/ 4)
После выполнения всех тестов, PHPUnit выводит сводную таблицу с процентом покрытия кода тестами. В примере выше видно, что в классе PHP\Package\User покрыто 100% кода. Обратите внимание, что покрытие сильно зависит от того, какие тесты выполнились. Если часть из них упала с ошибками, то PHPUnit покажет намного меньшее покрытие — тесты просто не доберутся до всего кода. Поэтому покрытие измеряют, только когда все тесты зеленые.
Различные флаги для генерации отчетов позволяют создавать отчеты в разных форматах. Например, флаг --coverage-html /path/to/report
создает человекочитаемый отчет, который можно просматривать в браузере:
Эта статистика помогает найти места, где тестов мало. Дальше по ситуации их можно начинать добавлять. Если в проекте тестов не было вообще, то эта статистика начинает быстро расти. А вот дальше, ближе к 90 процентам, придется бороться за каждую строчку кода.
Покрытие само по себе не гарантирует, что код работает правильно во всех ситуациях. Логические ошибки в коде невозможно отследить только покрытием. Для этого нужны тесты на одну и ту же функциональность, но с разным набором данных. Как правило, это тесты на пограничные случаи. В разработке есть хорошая практика: перед тем как чинить баги, сначала нужно написать тесты, которые их воспроизводят, и только затем уже можно починить их.
Какое покрытие считается допустимым? 100% покрытия выглядит красиво, но добиться его невероятно сложно. И для большинства проектов бессмысленно. Затраченные усилия не окупятся. Большинство разработчиков сходится во мнении, что 80% — это достаточно хорошее покрытие. На этом можно и остановиться.
Самостоятельная работа
- Клонируйте репозиторий php-package
- Запустите тесты и посмотрите на их вывод
- Добавьте флаг
--coverage-text
при запуске тестов и посмотрите, как изменился вывод - Добавьте флаг
--coverage-html coverage
при запуске тестов - Откройте созданную директорию coverage и запустите внутри нее файл index.html
- Изучите отчет по покрытию
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.