Тестирование (testing)
Главное правило тестирования в Go: файлы с тестами должны называться название_файла_test.go и лежать в той же папке, что и тестируемый код.
1. Unit-тесты: Простейший пример
Предположим, у нас есть файл math.go с функцией:
func Add(a, b int) int {
return a + b
}
Создаем файл math_test.go:
package main
import "testing"
// Имя функции должно начинаться с Test и принимать *testing.T
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
// t.Errorf помечает тест как проваленный и выводит ошибку
t.Errorf("Ожидалось %d, получено %d", expected, result)
}
}
Чтобы запустить тест, в терминале введите:
go test -v ./... (флаг -v показывает подробный вывод).
2. Табличное тестирование (Table-Driven Tests)
Это "золотой стандарт" Go. Вместо того чтобы писать 10 разных функций для проверки разных сценариев, вы создаете таблицу входных данных и ожидаемых результатов.
func TestAddTable(t *testing.T) {
// Таблица данных
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -1, -2},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
// t.Run создает "подтест" — удобно для отладки конкретного случая
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Ошибка в %s: ожидалось %d, получено %d", tt.name, tt.expected, result)
}
})
}
}
3. Как проверить, что функция паникует?
Иногда нам нужно убедиться, что код правильно реагирует на критическую ошибку (panic).
func TestDivideByZero(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("Функция должна была запаниковать, но не запаниковала")
}
}()
// Вызываем функцию, которая должна вызвать panic
// Например: Divide(10, 0)
}
4. Бенчмарки (Производительность)
Go позволяет измерять скорость выполнения кода с помощью тех же тестов. Функция должна начинаться с Benchmark.
func BenchmarkAdd(b *testing.B) {
// b.N — это число, которое Go подбирает сам, чтобы получить точный результат
for i := 0; i < b.N; i++ {
Add(1, 2)
}
}
Запуск: go test -bench=.
5. Зачем нам это? (Культура тестирования)
- Гарантия рефакторинга: Вы можете переписать внутренности функции
Add, и если тесты проходят — вы ничего не сломали. - Документация: Тесты показывают, как правильно использовать вашу функцию (какие аргументы подавать и что ожидать на выходе).
- CI/CD: Современные системы сборки не дадут вам выложить код в продакшн, если хотя бы один тест провален.
Золотые правила тестирования в Go:
- Один тест — одна логическая проверка.
- Используйте табличные тесты для проверки набора крайних случаев (edge cases).
- Не тестируйте приватные методы напрямую. Если вам нужно протестировать приватную логику, значит, ваша функция делает слишком много — разбейте её на части.
- Всегда проверяйте покрытие:
go test -coverпокажет, какой процент вашего кода реально покрыт тестами.