В процессе создания приложения и написания тестов может возникнуть необходимость разделить тесты на
две группы интеграционные тесты зависящие от окружения и unit тесты которые не зависят от окружения.
Для таких ситуации рекомендую использовать флаг -short
уже встроенный в go test -short ./...
, во
многих случаях этого простого деления будет достаточно, и более сложные механизмы вам не пригодятся.
Как это выглядит на практике:
go test -count=1 ./...
— для запуска всех тестов.go test -short ./...
— для запуска только unit тестов.
Ещё для того чтобы этот подход заработал корректно во всех интеграционных тестах нужно будет
добавить конструкцию вида if testing.Short() {}
:
func TestJustDoItCommandHandler_Handle(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode")
}
// ...
}
В Makefile такой подход может выглядеть следующим образом:
make test
— для запуска всех тестов.make test-short
— для запуска только unit тестов.
.PHONY: test
test: ## Run all tests.
@go test -count=1 ./...
.PHONY: test-short
test-short: ## Run only unit tests, tests without I/O dependencies.
@go test -short ./...
Так, подождите, а зачем вообще -count=1
? — Этот флаг нужен, чтобы очищать кеш тестов перед
прогоном интеграционных тестов, да если вы вдруг не знали Go кеширует результаты тестов, что весьма
не плохо для unit-тестов, но для интеграционных тестов это может стать проблемой потому что
результаты их зависят не только от изменений в коде, но и от изменений в окружении.
Для сброса кеша тестов в Go идиоматичным считается использование флага -count=1
, альтернативой
этому служит команда go clean -testcache
. Подробнее можно ознакомиться с описанием
воспользовавшись командами go help testflag
и go help clean
.
Альтернативы
- Build tags (1,2) - При таком подходе в файлах с тестами указывает тег сборки
например
integration
и такие тесты запускаются командойgo test -tags=integration
. У этого подхода есть множество проблем с тем что, линтеры начинают пропускать такие файлы, IDE могут не отображать корректно код или не запускать тесты без добавления тега сборки, и так далее. - Environment variables (3) - Способ похож на использование флага
-short
но только условный оператор уже ориентируется на переменную окруженияif os.Getenv("...") == "" {}
.
Глоссарий
- Интеграционный тест – в рамках этой статьи таким тестом буду называть любой тест работающий с I/O,
на практике это чаще всего тесты которые требуют наличия в окружении определенной зависимости,
базы данных, SMTP сервера, очередь сообщений, специфическую FS если вдруг наш код завязан на
тонкости определенной файлов системы, и так далее. Но также допускаю что если для работы теста
нужно запустить
http.Server{}
прямо из кода теста и этот тест не зависит от окружения, то не обязательно помечать его как интеграционный. - Unit тест - определение для таких тестов может тоже сильно разниться, в данной статье это любые тесты которые не зависят от окружения и условно запускаются и проходят на “всех” компьютерах.