Первый тест на Go: пошаговая инструкция для новичков
Go поставляется с собственным тестовым фреймворком прямо в стандартной библиотеке — ничего ставить не нужно. Разберём, как написать, запустить и прочитать результат первого теста за пятнадцать минут.

Что понадобится до начала
Прежде чем писать тест, убедитесь, что на машине стоит Go версии 1.21 или новее. Проверьте командой:
go version
# Ожидаемый вывод: go version go1.21.x (или выше) linux/amd64
Если команда не найдена — установите Go с официального сайта. Редактор подойдёт любой, но VS Code с расширением Go или GoLand покажут ошибки прямо при наборе.
Вам также нужна инициализированная Go-модуль. Если проекта ещё нет, создайте папку и выполните:
mkdir myproject && cd myproject
go mod init example.com/myproject
После этого в папке появится файл go.mod. Это минимальная заготовка — можно писать код и тесты.
Шаг 1. Напишите функцию, которую будете тестировать
Создайте файл calc.go в корне проекта:
// calc.go
package myproject
// Sum возвращает сумму двух целых чисел.
func Sum(a, b int) int {
return a + b
}
Проверка: запустите go build ./... — команда должна завершиться без вывода и без ошибок. Если видите сообщение об ошибке — проверьте, что имя пакета в calc.go совпадает с именем модуля (последняя часть пути в go mod init).
Шаг 2. Создайте файл теста
Go ищет тесты по двум признакам: имя файла заканчивается на _test.go, а имя функции начинается с Test и принимает аргумент *testing.T. Никакой магии аннотаций, декораторов или конфигов.
Создайте файл calc_test.go рядом с calc.go:
// calc_test.go
package myproject
import "testing"
func TestSumPositive(t *testing.T) {
result := Sum(2, 3)
expected := 5
if result != expected {
t.Errorf("Sum(2, 3) = %d; хотели %d", result, expected)
}
}
Обратите внимание: пакет тот же — myproject. Тест лежит в том же каталоге и видит неэкспортированные функции. Это так называемый white-box-тест.
В Go нет привычных assert-функций из коробки. Сравнение делается обычнымif, а о провале сообщаетt.Errorfилиt.Fatalf. Это сознательное решение дизайнеров языка: меньше магии — проще читать чужие тесты.
Проверка: файл calc_test.go существует, его пакет — myproject, функция начинается с Test и принимает *testing.T.
Шаг 3. Запустите тест
В корне проекта выполните:
go test -v
Флаг -v включает подробный вывод. Вы должны увидеть примерно следующее:
=== RUN TestSumPositive
--- PASS: TestSumPositive (0.00s)
PASS
ok example.com/myproject 0.002s
Строка PASS — тест прошёл. Если вместо неё FAIL — смотрите текст после ---, там будет сообщение из t.Errorf.
Шаг 4. Убедитесь, что тест действительно ловит ошибку
Хороший тест — тот, который падает, когда код сломан. Измените Sum так, чтобы она возвращала неправильный результат:
func Sum(a, b int) int {
return a * b // намеренная ошибка
}
Запустите go test -v снова. Теперь вывод будет таким:
=== RUN TestSumPositive
calc_test.go:10: Sum(2, 3) = 6; хотели 5
--- FAIL: TestSumPositive (0.00s)
FAIL
exit status 1
Вы видите имя файла, номер строки и ваше сообщение. Верните return a + b обратно, прежде чем двигаться дальше.
Шаг 5. Добавьте табличный тест
Один кейс — слабая защита. В Go принято группировать входные данные в слайс структур и прогонять их в цикле. Это называют table-driven test*.
func TestSumTable(t *testing.T) {
cases := []struct {
name string
a, b int
expected int
}{
{"два положительных", 2, 3, 5},
{"ноль и число", 0, 7, 7},
{"отрицательные", -1, -4, -5},
{"разные знаки", 10, -3, 7},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := Sum(tc.a, tc.b)
if result != tc.expected {
t.Errorf("Sum(%d, %d) = %d; хотели %d",
tc.a, tc.b, result, tc.expected)
}
})
}
}
t.Run создаёт подтест с именем из поля name. При запуске каждый подтест выводится отдельной строкой, и сразу видно, какой именно кейс упал.
Проверка: go test -v покажет четыре подтеста внутри TestSumTable, все со статусом PASS.
* Table-driven test — приём, при котором входные и ожидаемые значения описываются массивом структур, а тело теста — единственный цикл. Стандартный паттерн в Go, рекомендованный в официальном блоге проекта.
Полезные флаги go test
| Флаг | Что делает | Когда полезен |
|---|---|---|
-v | Подробный вывод каждого теста | Всегда при отладке |
-run TestSum | Запускает только тесты, чьё имя содержит «TestSum» | Когда тестов много, а чините один |
-count=1 | Отключает кеширование результатов | Когда go test пишет «(cached)» и вы не верите |
-cover | Показывает процент покрытия кода тестами | Перед коммитом, чтобы оценить пробелы |
-race | Включает детектор гонок данных | Если функция работает с горутинами |
Если не получилось
Ошибка: «no test files»
Файл теста не найден. Проверьте, что имя заканчивается именно на _test.go (не _tests.go, не test_.go) и что вы запускаете go test из того же каталога.
Ошибка: «cannot import» или «package … is not in std»
Скорее всего, нет файла go.mod. Вернитесь к разделу «Что понадобится» и выполните go mod init.
Тест не запускается, хотя файл есть
Имя функции должно начинаться с заглавной Test, а не test или TEST. Аргумент — ровно один, типа *testing.T. Если подпись другая, Go молча не считает функцию тестом.
Ошибка: «./calc_test.go:5: undefined: Sum»
Пакет в calc_test.go не совпадает с пакетом в calc.go. Откройте оба файла и убедитесь, что строка package одинаковая.
Вывод «PASS», но вы меняли код и ожидали «FAIL»
Go кеширует результаты тестов. Запустите go test -count=1 -v, чтобы выполнить тесты заново без кеша.
Что делать дальше
Тест написан и работает — теперь стоит двигаться по нарастающей:
- Добавьте тесты к реальной функции вашего проекта, а не только к учебной
Sum. - Попробуйте
go test -cover— посмотрите, какой процент строк покрыт, и решите, где пробелы критичны. - Изучите
t.Fatalf— он останавливает тест сразу, в отличие отt.Errorf, который продолжает выполнение. Полезно, когда дальнейшие проверки бессмысленны без первого условия. - Посмотрите пакет
testingв официальной документации: там же живут бенчмарки (Benchmark) и примеры (Example), которые тоже запускаются черезgo test.
Табличные тесты и стандартная библиотека покрывают большинство задач. Сторонние библиотеки вроде testify удобны, но не обязательны — начните без них, чтобы понять, как работает механизм изнутри.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: Официальная документация пакета testing — Go, How to Write Go Code — раздел Testing (Go Blog)
Частые вопросы
Нужно ли устанавливать отдельный фреймворк для тестов в Go?
Почему в Go нет assert, как в Python или JUnit?
Можно ли запустить один конкретный тест, а не все сразу?
Что если у меня другая версия Go — 1.18, 1.19?
Тест прошёл, но go test пишет «(cached)» — это нормально?
Где должен лежать файл теста — в отдельной папке?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.