Ответ
Главное — понимать, что покрытие тестами (code coverage) — это полезная метрика, но не самоцель. Высокий процент покрытия не гарантирует отсутствие багов, а лишь показывает, какая часть кода была выполнена во время тестов.
Наш подход строится на нескольких принципах:
-
Дифференцированные цели. Мы не гонимся за одинаковым процентом для всего проекта:
- Критически важная бизнес-логика, пакеты с алгоритмами: стремимся к 85-90%+.
- Стандартный код (контроллеры, CRUD): достаточно 70-80%.
- Код, который сложно тестировать (например, интеграции с UI): покрываем юнит-тестами по возможности, основной упор делаем на ручное или E2E-тестирование.
-
Качество важнее количества. Один тест на пограничный случай (edge case) или обработку ошибки ценнее десяти тестов, проверяющих "счастливый путь" (happy path).
-
Автоматизация в CI/CD. Проверка покрытия встроена в наш CI-пайплайн. Пул-реквест не может быть смержен, если покрытие нового или измененного кода падает ниже установленного порога (например, 80%).
# Пример команды для проверки покрытия go test -coverprofile=coverage.out ./... go tool cover -func=coverage.out # Вывод может выглядеть так: # ok project/pkg/utils 0.002s coverage: 85.2% of statements
-
Прагматичный подход к легаси. Мы не ставим задачу покрыть тестами весь старый код сразу. Но любое изменение или исправление бага в легаси-коде обязательно сопровождается написанием тестов для затрагиваемой логики.
Важное дополнение
Мы не стремимся к 100% покрытию, так как это часто экономически нецелесообразно (закон убывающей отдачи). Гораздо важнее иметь осмысленные интеграционные и E2E тесты, которые проверяют работу системы в целом, даже если они не влияют на метрику покрытия unit-тестами.