15 вопросов
Встроенная система тестирования Go: пакет testing, файлы _test.go, бенчмарки, параллельные тесты. Всё работает из коробки без внешних фреймворков.
Пакет testing - стандартный для юнит-тестов, бенчмарков и примеров. Запуск: go test. Go не использует внешние фреймворки - всё встроено в стандартную библиотеку.
Подробнее →Тестовые функции начинаются с Test, принимают *testing.T. Пример: func TestAdd(t *testing.T). Бенчмарки начинаются с Benchmark, фаззинг - с Fuzz.
Подробнее →Файлы *_test.go исключаются из обычной сборки и компилируются только при go test. Это позволяет держать тесты рядом с кодом без увеличения размера бинарника.
Подробнее →Table-driven tests: массив структур с входными данными и ожидаемым результатом + цикл с t.Run(name, func). Легко добавить новый кейс, чётко видны все сценарии, удобный вывод. Это стандарт в Go-сообществе и стандартной библиотеке.
Подробнее →-race при запуске go test -race? 🟢 Лёгкий
▶
Race detector инструментирует код и при выполнении обнаруживает одновременный несинхронизированный доступ к памяти. Замедляет в 2-20 раз. Рекомендуется в CI. Находит только гонки, которые реально произошли при выполнении - не статический анализ.
Подробнее →go test -bench=. запускает все BenchmarkXxx(b *testing.B). Тело выполняется b.N раз (Go подбирает N). -benchmem показывает аллокации. -count=5 запускает несколько раз для статистики. benchstat сравнивает результаты до и после оптимизации.
Подробнее →Фаззинг автоматически генерирует случайные входные данные и ищет входы, вызывающие панику или ошибку. Встроен в Go с версии 1.18.
Подробнее →t.Parallel()? 🟡 Средний
▶
t.Parallel() в начале теста разрешает запускать его параллельно с другими "параллельными" тестами. По умолчанию тесты выполняются последовательно. Полезно для ускорения.
Подробнее →Бенчмарки измеряют производительность. func BenchmarkX(b *testing.B) { for i := 0; i < b.N; i++ { ... } }. Запуск: go test -bench=. Go автоматически подбирает b.N.
Подробнее →Флаг -run принимает регулярное выражение. go test -run=TestAdd запустит только тесты, чьё имя совпадает с паттерном. Можно уточнять подтесты: -run=TestAdd/negative.
Подробнее →t.Helper() в тестовой функции? 🟡 Средний
▶
t.Helper() помечает функцию как вспомогательную. При вызове t.Error() или t.Fatal() в такой функции, в выводе будет показана строка вызывающего кода, а не строка внутри хелпера. Это делает сообщения об ошибках более полезными.
Подробнее →testing.TB? 🟡 Средний
▶
testing.TB - интерфейс, реализуемый и *testing.T (тесты), и *testing.B (бенчмарки). Позволяет писать хелперы, работающие и в тестах, и в бенчмарках: func setup(tb testing.TB) { tb.Helper(); ... }. Включает методы Error, Fatal, Log, Helper, Cleanup.
Подробнее →net/http/pprof встраивает профайлер в HTTP-сервер. Эндпоинты: /debug/pprof/profile (CPU), /debug/pprof/heap (память), /debug/pprof/goroutine. go tool pprof визуализирует. Overhead минимален - можно использовать в production.
Подробнее →Fuzz-тесты: FuzzXxx(f *testing.F), f.Add() задает seed-корпус, f.Fuzz() запускает генерацию. Запуск: go test -fuzz=FuzzXxx.
Подробнее →func TestMain(m *testing.M), но не вызвать m.Run()? 🔴 Сложный
▶
TestMain позволяет выполнить setup/teardown для всего пакета тестов. Если TestMain определена, go test вызывает её вместо автоматического запуска тестов. Без вызова m.Run() ни один Test* не выполнится. Паттерн: setup, code := m.Run(), teardown, os.Exit(code).
Подробнее →