Avatar ·

Как запустить конкретный тест или все тесты из указанного файла в Go?

Всем привет! Только начал изучать Go и пишу тесты для своего пакета. У меня есть файл `math_utils_test.go`, в котором лежит несколько тестовых функций: `TestAdd`, `TestSubtract` и `TestMultiply`. Я хочу запустить только один из них, например `TestAdd`. Пробовал команду `go test -run TestAdd`, но она запускает все тесты, в названии которых есть "TestAdd", даже из других файлов. А как запустить все тесты только из одного конкретного файла `math_utils_test.go`, игнорируя остальные? Я пробовал `go test math_utils_test.go`, но получаю ошибку, что не может найти функции из основного кода. Мой основной код лежит в `math_utils.go`. Подскажите, как правильно это сделать? Вот пример структуры моего проекта: ``` mypackage/ ├── math_utils.go ├── math_utils_test.go ├── string_utils.go └── string_utils_test.go ``` Пример кода из `math_utils_test.go`: ```go package mypackage import "testing" func TestAdd(t *testing.T) { result := Add(2, 3) if result != 5 { t.Errorf("Add(2, 3) = %d; want 5", result) } } func TestSubtract(t *testing.T) { result := Subtract(5, 3) if result != 2 { t.Errorf("Subtract(5, 3) = %d; want 2", result) } } ``` Заранее спасибо за помощь! <<>>

Краткий ответ

В Go нет прямой команды для запуска тестов только из одного файла в изоляции, потому что Go компилирует тесты на уровне пакета, а не файла. Однако есть два рабочих подхода:

Способ 1: Запуск конкретного теста по имени (рекомендуется)

Используйте флаг -run с регулярным выражением. Чтобы запустить только TestAdd из файла math_utils_test.go, выполните:

go test -run ^TestAdd$ ./mypackage

Символы ^ и $ означают "строгое совпадение с начала и до конца имени". Если у вас в разных файлах есть функции с одинаковыми именами, этот способ всё равно запустит все совпадения. Но в большинстве случаев имена тестов уникальны.

Способ 2: Фильтрация по файлу через build tags (продвинутый)

Если вам жизненно необходимо запускать тесты только из одного файла, используйте build-теги. Добавьте в начало файла math_utils_test.go строку:

//go:build math_tests

Теперь запускайте тесты с тегом:

go test -tags math_tests ./mypackage

Недостаток: нужно модифицировать файлы и помнить про теги.

Способ 3: Запуск всех тестов пакета (самый простой)

Просто выполните:

go test ./mypackage

Это запустит все тесты из пакета mypackage, включая string_utils_test.go. Если вы хотите ограничиться только математическими тестами, используйте -run с регулярным выражением, которое покрывает все ваши тесты из этого файла, например:

go test -run "Test(Add|Subtract|Multiply)" ./mypackage

Почему не работает go test math_utils_test.go?

Когда вы передаёте конкретный файл в go test, Go пытается скомпилировать только этот файл как изолированный тест. Он не видит другие файлы пакета (например, math_utils.go с определением функции Add), поэтому возникает ошибка "undefined: Add".

Правильный синтаксис — указывать путь к пакету, а не к файлу:

go test ./mypackage

Дополнительные советы

  • Флаг -v — показывает подробный вывод каждого теста: go test -v -run TestAdd ./mypackage
  • Флаг -count=1 — отключает кеширование результатов: go test -count=1 -run TestAdd ./mypackage
  • Флаг -list — просто выводит список всех тестов без запуска: go test -list . ./mypackage

Итог

Используйте go test -run ^TestName$ ./path/to/package. Это стандартный идиоматичный способ в Go. Если нужно запустить группу тестов из одного файла — объедините их имена через регулярное выражение. Build-теги используйте только в крайнем случае, когда без файловой изоляции никак (например, для тестов с разными платформами).

<<>>

Альтернативный подход: Использование подтестов (subtests)

Если вы хотите группировать тесты по логическим блокам и запускать их выборочно, рассмотрите использование подтестов. Это более идиоматичный способ для Go, чем фильтрация по файлам.

Пример рефакторинга вашего math_utils_test.go:

package mypackage

import "testing"

func TestMathOperations(t *testing.T) {
    t.Run("Add", func(t *testing.T) {
        result := Add(2, 3)
        if result != 5 {
            t.Errorf("Add(2, 3) = %d; want 5", result)
        }
    })

    t.Run("Subtract", func(t *testing.T) {
        result := Subtract(5, 3)
        if result != 2 {
            t.Errorf("Subtract(5, 3) = %d; want 2", result)
        }
    })
}

Теперь вы можете запустить только подтест "Add" из этого файла:

go test -run "TestMathOperations/Add" ./mypackage

Преимущества:

  • Не нужно менять структуру файлов или использовать build-теги
  • Подтесты наследуют фикстуры и настройки родительского теста
  • Удобно для параметризованных тестов (table-driven tests)
  • Лучшая читаемость и поддержка

Недостаток: требует рефакторинга существующих тестов, но это окупается на больших проектах.