Какое покрытие тестами считается нормальным и приемлемым
Что проверяют
Понимаете ли вы, что покрытие это индикатор непроверенного кода, а не мера качества тестов. Точной нормы нет, и интервьюер ждёт не цифру, а рассуждение о том, где покрытие важно и чем его измеряют в Go. Следом часто спрашивают, как посчитать покрытие интеграционных тестов.
Как отвечать
Сначала ориентир, с оговоркой. Для прикладного сервиса на Go нормальным обычно считают от 70 до 80% по пакетам с бизнес-логикой. В известной статье Google Testing Blog ориентиры такие: 60% приемлемо, 75% хорошо, 90% образцово. Но важнее распределение: доменная логика, парсеры, расчёты денег покрываются почти целиком, а main.go, сгенерированный код и тонкие обёртки над драйвером можно не трогать.
Дальше инструменты, их любят спрашивать:
go test -cover ./...: процент по каждому пакету;-coverprofile=cover.out: профиль, который смотрят черезgo tool cover -func=cover.outили-html=cover.out, чтобы увидеть непокрытые строки;-coverpkg=./...: засчитывает покрытие кода других пакетов, по умолчанию учитывается только тестируемый пакет;-covermode:set,countилиatomic, последний включается сам при-race;go build -cover: с Go 1.20 можно собрать инструментированный бинарник, прогнать на нём интеграционные тесты и собрать данные черезGOCOVERDIRиgo tool covdata.
Учтите, что в Go покрытие считается по операторам, покрытия ветвей из коробки нет. Проверить силу тестов помогает мутационное тестирование, а в CI полезнее правило «покрытие изменённого кода не падает», чем жёсткий общий порог.
Где спотыкаются
Называют одну цифру для всего проекта. Средние 80% легко получаются за счёт хорошо покрытых утилит при нулевом покрытии обработчиков ошибок.
Гонятся за 100% и пишут тесты без проверок: код выполнился, строки зелёные, но ни одного t.Errorf в тесте нет.
Забывают про ветки if err != nil. Именно они чаще всего не покрыты, и именно там живут падения в проде. Их проверяют через фейковые реализации интерфейсов, которые возвращают ошибку.