«А можно запустить только один файл с тестами?» — да, и вот как это сделать в Go
Вы когда-нибудь сидели перед терминалом, набирали go test ./... и с ужасом наблюдали, как вся кодовая база вашего проекта на Go начинает прогонять сотни тестов? А ведь вам нужно было проверить только один маленький файл с тест-кейсами, который вы только что дописали. Знакомо? Если да — вы пришли по адресу.
В этой статье мы разберём популярный вопрос с Stack Overflow (кстати, у него тысячи просмотров): «How to run test cases in a specified file?». Мы адаптируем ответы под реалии Go-разработчика и покажем не только базовые команды, но и лайфхаки, которые сэкономят вам часы работы. Поехали!
Почему просто go test не всегда подходит?
В больших проектах тесты делятся на модульные, интеграционные и end-to-end. Если вы запускаете go test ./..., Go рекурсивно обходит все подпакеты и выполняет все найденные тесты. Это может занять минуты. А если у вас есть тесты, которые обращаются к базе данных или внешним API, они могут упасть по независящим от вас причинам. Поэтому умение запустить тест-кейсы в указанном файле — это не просто удобство, а навык профессионального разработчика.
Базовая команда: go test с именем файла
Самый прямолинейный способ — указать конкретный файл с тестами. Но здесь есть нюанс: Go требует, чтобы вы указали и тестируемый файл, и файл с тестами вместе. Почему? Потому что компилятор должен собрать весь код пакета.
Допустим, у вас есть структура проекта:
myproject/
├── main.go
└── math_utils.go
└── math_utils_test.go
Чтобы запустить тесты только из math_utils_test.go, выполните:
go test -v math_utils.go math_utils_test.go
Флаг -v (verbose) выведет подробную информацию о каждом тест-кейсе. Без него вы увидите только итог: PASS или FAIL.
Пример реального кода
Создадим простой файл math_utils.go:
package main
func Sum(a, b int) int {
return a + b
}
func Multiply(a, b int) int {
return a * b
}
И тест-файл math_utils_test.go:
package main
import "testing"
func TestSum(t *testing.T) {
result := Sum(2, 3)
if result != 5 {
t.Errorf("Sum(2, 3) = %d; want 5", result)
}
}
func TestMultiply(t *testing.T) {
result := Multiply(3, 4)
if result != 12 {
t.Errorf("Multiply(3, 4) = %d; want 12", result)
}
}
Теперь запускаем:
$ go test -v math_utils.go math_utils_test.go
=== RUN TestSum
--- PASS: TestSum (0.00s)
=== RUN TestMultiply
--- PASS: TestMultiply (0.00s)
PASS
ok command-line-arguments 0.002s
Обратите внимание на вывод: ok command-line-arguments. Это означает, что Go собрал временный пакет из указанных файлов. Такой подход работает, но имеет ограничения.
Проблема с несколькими файлами в одном пакете
Если ваш пакет состоит из нескольких файлов (например, math_utils.go и strings_utils.go), и тест в math_utils_test.go вызывает функцию из strings_utils.go, то команда выше упадёт с ошибкой компиляции. Go будет ругаться, что функция не определена.
Решение — перечислить все зависимые файлы. Но это неудобно. Лучше использовать другой подход.
Продвинутый способ: фильтрация тестов по имени (-run)
Флаг -run позволяет запустить только те тест-кейсы, имена которых соответствуют регулярному выражению. Это не привязка к файлу, но если вы назвали тесты осмысленно, то легко отфильтруете нужные.
Пример: запустить все тесты, начинающиеся на TestSum:
go test -v -run TestSum ./...
Если хотите запустить только тесты из конкретного файла, можно использовать паттерн по имени файла в имени теста. Например, назовите тесты так: TestFile_MathUtils_Sum. Тогда:
go test -v -run TestFile_MathUtils ./...
Это неочевидный, но рабочий трюк, который используют опытные Go-разработчики.
Работа с разными пакетами: go test ./package/...
Если ваш проект разбит на пакеты, вы можете ограничить область поиска до одного пакета. Например, если тесты лежат в internal/calculator/, выполните:
go test -v ./internal/calculator/...
Go просканирует только этот пакет и его подпакеты. Это быстрее, чем ./..., и не затронет другие модули.
Самый правильный способ: использовать go test с путём к пакету
Если вам нужно запустить все тесты из определённого файла в рамках одного пакета, лучше всего перейти в директорию пакета и выполнить:
cd internal/calculator
go test -v
Go сам найдёт все файлы *_test.go в текущем пакете. Если вы хотите запустить только один файл — вернитесь к первому способу, но не забывайте про зависимые файлы.
Лайфхак: ignore-файлы для быстрого исключения
Иногда нужно временно исключить файл из тестирования. Вместо того чтобы удалять его, можно переименовать, убрав суффикс _test. Go не увидит его как тестовый файл. После работы верните имя обратно.
Пример:
mv math_utils_test.go math_utils_test.go.bak
go test -v ./...
mv math_utils_test.go.bak math_utils_test.go
Это не элегантно, но работает за секунду.
Сравнение подходов: что выбрать?
- Один файл без зависимостей —
go test file.go file_test.go - Один файл с зависимостями в пакете — перечислите все файлы или используйте
-runс именем теста - Все тесты в одном пакете —
go test ./package/ - Фильтрация по имени теста —
go test -run "TestName" ./...