Создание тестов в 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/op$$
BenchmarkSum-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
Вывод:
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