Как контролируешь уровень покрытия тестов?

«Как контролируешь уровень покрытия тестов?» — вопрос из категории Тестирование, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Я контролирую покрытие кода тестами как на локальной машине разработчика, так и автоматически в CI/CD пайплайне, используя инструменты, входящие в стек PHP.

Основной инструмент — PHPUnit с Xdebug или PCOV: Конфигурация в phpunit.xml:

<phpunit ...>
    <coverage>
        <include>
            <directory suffix=".php">src</directory>
        </include>
        <exclude>
            <directory>src/Migrations</directory> <!-- Исключаем миграции -->
            <file>src/Entity/AbstractEntity.php</file> <!-- Исключаем абстрактные классы -->
        </exclude>
        <report>
            <html outputDirectory="var/coverage/html"/>
            <clover outputFile="var/coverage/clover.xml"/>
        </report>
    </coverage>
</phpunit>

Стратегия контроля в CI/CD (GitLab CI пример):

test:coverage:
  script:
    - vendor/bin/phpunit --coverage-text --coverage-clover var/coverage/clover.xml
  coverage: '/s*Lines:s*(d+.d+)%/' # Извлечение метрики для badge

  # Проверка на минимальный порог покрытия
    - >
      COVERAGE=$(vendor/bin/phpunit --coverage-text 2>&1 | grep 'Lines' | awk '{print $2}' | sed 's/%//');
      if (( $(echo "$COVERAGE < 80" | bc -l) )); then
        echo "Coverage $COVERAGE% is below required 80%" && exit 1;
      fi

Что именно я контролирую и как:

  1. Минимальный порог по строкам кода (line coverage): В CI пайплайне падает, если покрытие падает ниже 80% (значение зависит от проекта). Это защищает от регрессии.
  2. Анализ отчёта, а не только процента: Регулярно смотрю HTML-отчёт, чтобы выявить непокрытые важные ветвления (branch coverage), например, обработку ошибок или edge-кейсы в условных операторах.
  3. Мутационное тестирование для качества тестов: Использую Infection для борьбы с «лжеположительным» покрытием, когда тесты есть, но они не проверяют логику по-настоящему. Инструмент вносит мелкие изменения в код (мутации), и хорошие тесты должны эти мутации «убивать».
    infection --threads=4 --coverage=var/coverage --min-msi=70
  4. Фокус на критической логике: Не гонюсь за 100% покрытием. Приоритет — покрытие модулей с бизнес-логикой, расчётами, обработкой платежей. Вспомогательные классы, DTO, простые геттеры/сеттеры могут иметь меньшее покрытие.