Какие тесты пишутся при разработке логики
Что проверяют
Знаете ли вы, что в Go тесты строятся на стандартном пакете testing, и умеете ли подобрать вид теста под задачу: логику, взаимодействие с базой, конкурентный код. Следом обычно просят показать табличный тест или объяснить, как вы подменяете зависимости.
Как отвечать
Идите от самого частого к редкому:
- юнит-тесты: функции
TestXxx(t *testing.T)в файлах_test.go, запуск черезgo test ./.... Стандарт де-факто это табличные тесты: срез структур с входом и ожиданием, каждый случай вt.Run(tc.name, ...); - подмена зависимостей: через маленькие интерфейсы на стороне потребителя. Моки генерируют
go.uber.org/mock(форк архивированногоgolang/mock) или mockery, а часто хватает рукописной заглушки. Для HTTP естьhttptest.NewServerиhttptest.NewRecorder; - интеграционные: реальная база в testcontainers-go, отделяются тегом сборки
//go:build integrationили проверкойtesting.Short(); - бенчмарки:
BenchmarkXxx(b *testing.B), запуск с флагами-benchи-benchmem. В свежих версиях Go цикл удобнее писать черезb.Loop(); - фаззинг:
FuzzXxx(f *testing.F), встроен начиная с Go 1.18, хорошо ловит паники на разборе входных данных; - примеры:
ExampleXxxс комментарием// Output:, одновременно документация и тест.
Обязательно назовите go test -race: детектор гонок в CI ловит то, что обычный прогон не покажет. Для проверок многие берут testify с require и assert, для очистки ресурсов есть t.Cleanup, для параллельного запуска t.Parallel().
Где спотыкаются
Пишут time.Sleep в тестах конкурентного кода. Тест становится медленным и мигающим, лучше синхронизироваться каналами или sync.WaitGroup.
Мокают всё, включая собственные структуры, и заводят огромные интерфейсы. В Go интерфейс объявляет потребитель, и в нём обычно два-три метода.
Путают assert и require из testify: после неудачного assert тест продолжается и падает дальше на nil-указателе, скрывая первую причину.