Ответ
Юнит-тесты (модульные тесты) — это тип автоматизированных тестов, которые проверяют корректность работы наименьших изолированных частей программы, таких как функции или методы.
Основные цели юнит-тестов:
- Обнаружение ошибок на ранней стадии: Позволяют быстро найти и исправить баги в новой или измененной логике.
- Безопасный рефакторинг: Если после изменения кода тесты по-прежнему проходят, вы можете быть уверены, что не сломали существующую функциональность.
- Живая документация: Тесты наглядно демонстрируют, как должен работать код и какие крайние случаи (edge cases) он обрабатывает.
- Улучшение дизайна кода: Необходимость писать тестируемый код подталкивает к созданию более слабосвязанных и модульных компонентов.
Пример в Go:
Для написания тестов в Go используется встроенный пакет testing
. Тестовые функции должны начинаться с Test
, находиться в файлах _test.go
и принимать *testing.T
в качестве аргумента.
Код для тестирования:
// file: sum.go
func Sum(a, b int) int {
return a + b
}
Простой юнит-тест:
// file: sum_test.go
package main
import "testing"
func TestSum(t *testing.T) {
result := Sum(2, 3)
expected := 5
if result != expected {
t.Errorf("Sum(2, 3) = %d; ожидалось %d", result, expected)
}
}
Лучшая практика в Go: Table-Driven Tests
Для проверки нескольких сценариев принято использовать табличные тесты. Это делает тест более читаемым и легко расширяемым.
// file: sum_test.go
func TestSumTable(t *testing.T) {
cases := []struct {
name string
a, b int
expected int
}{
{"Положительные числа", 2, 3, 5},
{"Отрицательные числа", -2, -3, -5},
{"Смешанные числа", 2, -3, -1},
{"С нулем", 5, 0, 5},
}
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)
}
})
}
}
Запуск тестов выполняется командой: go test
.