раздел 11 · рецепт

Поднять test coverage до 80%

«Напиши тесты для всего» - худший промпт. Получите 200 бесполезных тестов, которые проверяют, что 1 + 1 = 2, и пропускают реальные баги. Этот рецепт - как поднять coverage до значимых 80%, тестируя то, что важно, а не то, что просто.

Когда применять

  • Coverage низкий (< 40%), а тесты нужны для рефакторинга или прод-нагрузки
  • Перед большим релизом - хочется уверенности
  • После прод-инцидента - чтобы не повторилось
  • Новый проект - заложить культуру тестов с начала

Шаги

Шаг 1. Замерить текущее покрытие

# Python
pytest --cov=app --cov-report=term-missing

# Node
pnpm test --coverage

Смотрите не на общий процент, а на:

  • Какие файлы покрыты 0%
  • Какие критические пути не тестируются вообще

Шаг 2. Identify критические пути

Промпт:
"Делегируй code-explorer: проанализируй кодобазу и составь список
10 критических путей - функций, без которых приложение неработоспособно.
Для каждого верни: путь к файлу, сигнатура, что делает, что произойдёт
если функция упадёт."

Получаете список приоритетов. Покрываете их первыми.

Шаг 3. План покрытия

Промпт:
"На основе списка критических путей и текущего покрытия pytest
составь план тестирования. Каждый пункт: что покрываем, какие
edge cases, какие моки нужны. Приоритет 1 - критические пути,
приоритет 2 - частые баги, приоритет 3 - утилиты."

Шаг 4. Пишем тесты пакетами

Не пишите тесты для всего проекта одним промптом. Делайте по модулю:

Промпт:
"Напиши pytest-тесты для app/services/payment.py.
Покрой: успешный платёж, недостаточно средств, неверный ID,
дублирующий платёж, отмена платежа. Используй фикстуры из
tests/conftest.py. Мокай anthropic.AsyncAnthropic и httpx.AsyncClient
через respx. Запусти тесты, убедись что проходят."

Шаг 5. Проверяем качество тестов

После написания тестов:

  • Запустите pytest -v - все ли описаны человеческим языком
  • Запустите pytest --cov - покрытие выросло?
  • Намеренно сломайте код в одном месте - падают ли тесты?
Промпт для последнего шага:
"Удали временно проверку balance < amount в payment.py (поставь True).
Запусти тесты. Какие упали? Если не упало ни одного - наши тесты плохие,
покажи мне какие edge cases мы пропустили."

Какие тесты важнее

Приоритеты по убыванию:

  1. Тесты-инварианты - проверяют, что код выполняет контракт. "После CreateUser в базе должен быть user."
  2. Тесты-регрессии - повторяют баг, который уже был в проде. После фикса всегда добавляйте такой тест.
  3. Тесты edge cases - граничные значения, пустые входы, отрицательные числа, очень длинные строки, юникод.
  4. Integration-тесты - проверяют связь компонентов (DB + API + handler).
  5. E2E-тесты - сценарии пользователя через браузер (Playwright). Дорогие, медленные, но ловят то, что юниты не ловят.

Игнорируйте:

  • Тесты геттеров/сеттеров без логики
  • Тесты, что import работает
  • Тесты, дублирующие проверки в самом коде (если функция возвращает int, не нужен тест что вернулся int)

Антипаттерны

| Что не делать | Почему | |---|---| | Coverage ради coverage | 90% мусорных тестов хуже 50% значимых. | | Мокать всё подряд | Получите тесты, которые проверяют, что мок ведёт себя как мок. | | Тестировать private-методы | Тестируйте через публичный API. | | Хрупкие e2e тесты | Падают от каждой смены текста в UI - выключают всю команду. | | Тесты с задержками (sleep 5) | Race conditions, нестабильность CI. |

Полезные ссылки