Avatar ·

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

Всем привет! Я только начал изучать Go и столкнулся с проблемой при запуске тестов. У меня есть проект со структурой: ``` myproject/ ├── main.go ├── handlers.go ├── handlers_test.go ├── utils.go └── utils_test.go ``` В файле `handlers_test.go` у меня несколько тестовых функций, а в `utils_test.go` — свои. Когда я запускаю `go test ./...`, выполняются все тесты из обоих файлов, и это нормально. Но иногда мне нужно запустить только тесты, которые находятся в `handlers_test.go`, не трогая `utils_test.go`. Я пробовал команду `go test handlers_test.go`, но получаю ошибку компиляции, потому что в тестовом файле используются функции из `handlers.go`, которые не подключаются автоматически. Например, в `handlers_test.go` у меня есть такой код: ```go package main import "testing" func TestHandleRequest(t *testing.T) { result := HandleRequest("test") // функция из handlers.go if result != "expected" { t.Errorf("got %v, want %v", result, "expected") } } ``` Как правильно запустить только тесты из конкретного файла, чтобы Go подхватил все необходимые зависимости? И можно ли как-то запустить один конкретный тест внутри файла? Заранее спасибо за помощь! <<>>

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

Проблема в том, что команда go test handlers_test.go пытается скомпилировать только указанный файл, но не подключает другие файлы пакета (например, handlers.go). В Go тесты работают на уровне пакета, поэтому нужно указывать либо весь пакет, либо все необходимые файлы.

Основное решение: используйте шаблон go test -run для фильтрации тестов по имени, а файлы указывайте все, которые нужны для компиляции:

go test -run "TestHandleRequest" handlers_test.go handlers.go

Но такой подход неудобен, если файлов много. Лучший способ — запускать тесты для всего пакета, но с фильтром по имени теста:

go test -v -run "TestHandleRequest" ./...

Эта команда запустит только тесты, имя которых содержит TestHandleRequest, во всех пакетах проекта. Флаг -v (verbose) покажет подробный вывод.

Запуск всех тестов из конкретного файла

Если нужно запустить все тесты из handlers_test.go, используйте регулярное выражение, которое соответствует всем тестам в этом файле. Обычно тесты именуются с префиксом, например TestHandle:

go test -v -run "TestHandle" ./...

Или можно запустить тесты только для конкретного пакета (если файлы находятся в отдельной папке):

go test -v ./handlers/

Запуск одного конкретного теста

Для запуска одного теста используйте флаг -run с точным именем:

go test -v -run "^TestHandleRequest$" ./...

Символы ^ и $ — это якоря регулярного выражения, которые гарантируют точное совпадение имени.

Работа с зависимостями и тестовыми файлами

Если тесты используют вспомогательные функции из других файлов того же пакета (например, utils.go), их тоже нужно указывать в команде, если вы не используете ./...:

go test -v -run "TestHandle" handlers_test.go handlers.go utils.go

Но повторюсь: самый простой и правильный способ — запускать все тесты пакета с фильтром:

go test -v -run "TestHandle" ./

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

  • Используйте флаг -count=1, чтобы отключить кэширование результатов тестов: go test -count=1 -v -run "TestHandle" ./...
  • Для параллельного запуска добавьте -parallel N, где N — количество параллельных тестов.
  • Проверьте покрытие кода для конкретного теста: go test -cover -run "TestHandle" ./...
  • Используйте табличные тесты (table-driven tests), чтобы легко запускать отдельные подтесты по имени.

Пример табличного теста

func TestHandleRequest(t *testing.T) {
    tests := []struct {
        name string
        input string
        want string
    }{
        {"valid_input", "test", "expected"},
        {"empty_input", "", "error"},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := HandleRequest(tt.input)
            if got != tt.want {
                t.Errorf("got %v, want %v", got, tt.want)
            }
        })
    }
}

Теперь вы можете запустить только подтест valid_input:

go test -v -run "TestHandleRequest/valid_input" ./...
<<>>

Альтернативный подход: использование тегов сборки (build tags)

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

//go:build integration

package main

import "testing"

func TestIntegrationFeature(t *testing.T) {
    // ...
}

Теперь этот тест будет выполняться только при указании тега:

go test -tags=integration -v ./...

А обычные тесты (без тега) будут запускаться как обычно. Это удобно для разделения юнит-тестов и интеграционных тестов.

Использование Go 1.22+ для фильтрации по файлам

Начиная с Go 1.22, появилась возможность фильтровать тесты по исходному файлу через флаг -run с использованием синтаксиса file:testname. Пока эта функция экспериментальная, но в будущем может стать стандартной. Следите за обновлениями документации.

Работа в IDE

В большинстве IDE (VS Code с расширением Go, GoLand) есть возможность запустить конкретный тест прямо из редактора — нажмите на зелёную стрелку рядом с именем функции. Это самый простой способ для повседневной разработки.