Запуск тестов в Go: как прогнать только нужный файл? Полный гайд

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

«А можно запустить только один файл с тестами?» — да, и вот как это сделать в 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" ./...

Блоги

Рекомендаций по книгам