Создание тестов в GO
Categories:
Основные правила написания тестов в Go
-
Именование файлов:
- Тестовые файлы должны заканчиваться на
_test.go. - Пример:
main.go→main_test.go.
- Тестовые файлы должны заканчиваться на
-
Именование функций:
- Тестовые функции должны начинаться с
Test(для юнит-тестов) илиBenchmark(для бенчмарков). - Пример:
func TestAdd(t *testing.T) { ... } func BenchmarkAdd(b *testing.B) { ... }
- Тестовые функции должны начинаться с
-
Параметры тестовых функций:
- Юнит-тесты принимают
*testing.T. - Бенчмарки принимают
*testing.B. - Примеры тестов (
t.Error,t.Fail,t.Runдля подтестов).
- Юнит-тесты принимают
-
Табличные тесты (Table-Driven Tests):
- Рекомендуемый подход для покрытия разных сценариев.
- Пример:
func TestAdd(t *testing.T) { cases := []struct { a, b, expected int }{ {1, 2, 3}, {0, 0, 0}, {-1, 1, 0}, } for _, tc := range cases { result := Add(tc.a, tc.b) if result != tc.expected { t.Errorf("Add(%d, %d) = %d; want %d", tc.a, tc.b, result, tc.expected) } } }
-
Покрытие кода (Coverage):
- Замер покрытия:
go test -cover go test -coverprofile=coverage.out && go tool cover -html=coverage.out
- Замер покрытия:
-
Моки и тестовые данные:
- Используйте интерфейсы для замены зависимостей (например,
sqlmockдля тестирования SQL-запросов).
- Используйте интерфейсы для замены зависимостей (например,
Автоматизация тестов в Emacs для Go
-
go-mode:
- Основной режим для работы с Go в Emacs.
- Установка:
(use-package go-mode :ensure t)
-
go-test.el:
- Пакет для запуска тестов (встроен в
go-mode). - Команды:
M-x go-test-current-test— запуск текущего теста.M-x go-test-current-file— тестирование текущего файла.M-x go-test-current-project— тесты всего проекта.M-x go-test-current-benchmark— запуск бенчмарка.
- Пакет для запуска тестов (встроен в
-
flycheck / golangci-lint:
- Проверка кода и тестов в реальном времени.
-
dap-mode (Debug Adapter Protocol):
- Отладка тестов (аналог VS Code).
Требования к тестовым файлам
-
Расположение:
- Тестовые файлы должны быть в том же пакете (
package math→package math_testдля black-box тестирования).
- Тестовые файлы должны быть в том же пакете (
-
Доступ к символам:
- Если тестируемые функции/переменные должны быть экспортированы (
UpperCase).
- Если тестируемые функции/переменные должны быть экспортированы (
-
Использование
testing:- Обязателен импорт
"testing".
- Обязателен импорт
-
Тестовые данные:
- Можно использовать
testdata/для дополнительных файлов (например, JSON-фикстур).
- Можно использовать
Основные команды для тестов
-
Запуск всех тестов:
go test ./... -
Запуск конкретного теста:
go test -run TestAdd -
Покрытие кода:
go test -coverprofile=cover.out && go tool cover -html=cover.out -
Бенчмарки:
go test -bench . -
Пропуск кеширования:
go test -count=1 -
Вербозный вывод:
go test -v -
Параллельные тесты:
func TestParallel(t *testing.T) { t.Parallel() // ... }
Бенчмарки (Benchmarks) в Go
Бенчмарки в Go — это тесты производительности, которые измеряют скорость выполнения кода (время на операцию, аллокации памяти и т. д.). Они помогают находить узкие места в программе и сравнивать разные реализации алгоритмов.
Как работают бенчмарки?
-
Именование функции:
- Должно начинаться с
Benchmark. - Принимает
*testing.B(аналог*testing.Tв обычных тестах). - Пример:
func BenchmarkSum(b *testing.B) { for i := 0; i < b.N; i++ { Sum(1, 2) // Тестируемая функция } }
- Должно начинаться с
-
Цикл
b.N:- Go автоматически подбирает
N(количество итераций), чтобы получить стабильные результаты. - Чем быстрее функция, тем больше итераций будет сделано.
- Go автоматически подбирает
-
Запуск бенчмарка:
go test -bench .- Флаг
-benchпринимает регулярное выражение для выбора бенчмарков (.— все). - Пример вывода:
BenchmarkSum-8 1000000000 0.265 ns/opBenchmarkSum-8— название теста (-8— количество CPU).1000000000— количество итераций (b.N).0.265 ns/op— время на одну операцию (наносекунды).
- Флаг
Полезные флаги для бенчмарков
| Флаг | Описание | Пример |
|---|---|---|
-benchmem |
Показывать аллокации памяти | go test -bench . -benchmem |
-benchtime |
Установить время выполнения | go test -bench . -benchtime=5s |
-count |
Количество прогонов | go test -bench . -count=3 |
-cpu |
Тестировать на разном числе CPU | go test -bench . -cpu=1,2,4 |
Пример бенчмарка
Допустим, есть функция сложения:
// sum.go
package math
func Sum(a, b int) int {
return a + b
}
Тест и бенчмарк:
// sum_test.go
package math
import "testing"
func TestSum(t *testing.T) {
if Sum(1, 2) != 3 {
t.Error("Ожидается 3")
}
}
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
Sum(1, 2)
}
}
Запуск:
go test -bench . -benchmem
Вывод:
BenchmarkSum-8 1000000000 0.265 ns/op 0 B/op 0 allocs/op
0.265 ns/op— 0.265 наносекунд на операцию.0 B/op— 0 байт выделено за итерацию.0 allocs/op— 0 аллокаций памяти.
Сравнение производительности
Бенчмарки полезны для сравнения разных реализаций. Например:
func BenchmarkSlow(b *testing.B) {
for i := 0; i < b.N; i++ {
SlowFunction()
}
}
func BenchmarkFast(b *testing.B) {
for i := 0; i < b.N; i++ {
FastFunction()
}
}
Запуск:
go test -bench . -benchmem
Покажет, какая функция работает быстрее и использует меньше памяти.
Бенчмарки в Go — это тесты производительности.
- Запускаются через
go test -bench. - Показывают время на операцию (
ns/op), аллокации памяти (B/op,allocs/op).
Если нужно углублённо анализировать производительность, можно использовать pprof:
go test -bench . -cpuprofile=cpu.out
go tool pprof cpu.out