Бюрократия семимильными шагами внедряется в процесс разработки. Людей в пиджаках интересуют лишь цифры, и это же относится к test coverage сервисов. Однако, покрытие зачастую (в том числе, благодаря создателям языка) не отображает полной картины мира. Так ли все плохо на самом деле?     Разберем на примере простого сервиса. С таким методом, который мы хотим протестировать. В этом методе представлены большинство видов ошибок, которые могут быть в какой-либо функции. Давайте напишем тест. Вот только что для нас важно тестировать? Ошибки вида 3 тестировать не имеет смысла, т.к. все равно возвращаемое значение мы определяем сами в ходе теста за счет моков. Единственная польза от них, уберечь себя от случайного удаления существующей проверки на ошибку в функции, от чего отыгрывать странно и затратно по времени. Тоже и с ошибками вида 5, они либо же не под нашим контролем, либо же имеют специфичные кейсы для возникновения ошибок: например послать неверный формат данных в аргументы, что в теории воспроизводимо в тест кейсе, однако, почти не вероятны с реальными данными.  Ошибки вида 6 по-хорошему никогда не должны воспроизводиться, но они часто встречаются, в том числе и при вызове сторонних библиотек. Протестировать такой кейс зачастую не представляется возможным. Тестируем кейсы вида 1, 2, 4, 7   Маловато однако, давайте разбираться. Посмотрим на покрытие нашего метода в html 82.4% покрыто, нас это вполне устраивает, но в чем тогда загвоздка? Смотрим здесь же на весь coverage report. Видим мы то, что покрытие посчиталось там, где нам этого не нужно. Посмотрим на структуру нашего сервиса. Результат вполне закономерен, утилита cover по дефолту считает покрытие для всех гошных файлов* в директории, если в директории* находится хотя бы один тестовый файл Для начала, нужно избавиться от мок файлов в расчете покрытия, т.к. они обычно сгенерированы автоматически и могут содержать 1000+ строк кода. К сожалению, встроенные утилита в этом плане ограничена, поэтому можем воспользоваться такой хитростью. Записываем репорт покрытия в tmp файл; Копируем все в новый файл, кроме строк, заканчивающихся на тот паттерн, который вы используете при создании мок файлов. В данном случае это _mock.go; Удаляем tmp файл; Запускаем cover. И теперь покрытие 65.2%: Далее допустим, что в отделе мы договорились тестировать только бизнес логику, то бишь методы сервиса, а для проверки dal и app у нас есть e2e тесты, которые не отображаются в покрытии. Некоторые сущности тестировать нету никакого смысла, например методы моделек. В таком случае нам нужно слегка логически декомпозировать структуру сервиса. Отделив компоненты логически, мы не берем в расчет ненужные нам выражения, и получаем 83.3% покрытия при повторном запуске скрипта. Таким образом мы увеличили coverage с 20 до >80% не написав ни единой строчки кода.  Но все ли у нас хорошо теперь? Посмотрим на структуру сервисного слоя еще разок. А у нас оказывается есть еще и второй сервис без единого теста, который не отобразился в репорте, т.к. в нем нет тестов. Попробуем что-то с этим сделать: можно договориться, что все файлы в проекте под директорией bll  должны быть протестированы. Давайте попробуем это отобразить в репорте добавив флаг -coverpkg. Следовательно, получаем уже более подробную картину для нашего проекта, видя не протестированные компоненты логики. Дописав недостающие тесты, получаем 84.2%. Давайте вернемся к нашему первому тесту, тут еще остались некоторые тонкости.  По поводу кейса 6. Протестировать его мы не можем, и странно, что такой блок вообще попадает в репорт. Уместен был бы вопрос: а есть ли способы пометить некоторые куски кода как недосягаемые для покрытия, чтобы лишний раз не портить статистику, или же игнорировать конструкции по типу паник при подсчете покрытия? Этот вопрос обсуждался не раз на форумах и issue: 1, 2, но если вкратце, то примерный ответ на все предложения от комьюнити можно свести к этому комменту Роба Пайка в одном из похожих issue. Хотя, уже есть пару неофициальных библиотек, которые решают эту проблему. В этой статье я попытался разобрать частые ошибки и недопонимания при покрытии сервисов тестами, лучшие практики и открытые дискуссии комьюнити. Соц сети: https://www.linkedin.com/in/dishanov/ Еще одна особенность флага coverpkg, что если директория A добавлена в аргументы флага, то все выражения в ней при их вызове с теста директории B будут считаться покрытыми тестами в репорте, даже если к выражению не написаны точечные тесты.  В нашем тесте мы вызываем функцию HasDuplicates из директории helper, у которой нет тестов  Проверяем, включая internal/helper в coverpkg Видим, что выражение считается протестированным Иногда это бывает полезным, а зачастую может вредить как в нашем случае, ведь мы специально не тестировали этот метод в различных сценариях. *Есть один неочевидный момент. Баг это или фича, но даже если указать только './internal/helper/...'вcoverpkg, то функция будет тоже считаться покрытой из-за того, что мы по факту ее вызываем в тесте DoSmth и в  скрипте мы все еще тестируем все файлы в проекте: go test ./... Иной раз я встречал практику (крайне не рекомендую ее), когда все тесты писали в слое имплементации (app), а не в сервисном слое. В этом случае мы по факту тестируем полностью бизнес логику сервиса, но если не использовать coverpkg, то протестированный метод сервисного слоя в репорт не попадет, что не есть хорошо.  Golang backend developer