Unit-тесты (модульные тесты) — это фундаментальная практика тестирования отдельных изолированных компонентов (юнитов) программного обеспечения. В контексте Go это означает тестирование отдельных функций, методов или небольших модулей кода.
Пример тестируемой функции:
// math.go
package math
func Add(a, b int) int {
return a + b
}
Соответствующий unit-тест:
// math_test.go
package math
import "testing"
func TestAdd(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(tt.name, func(t *testing.T) {
if got := Add(tt.a, tt.b); got != tt.expected {
t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
}
})
}
}
Для изоляции тестируемого кода от внешних зависимостей используются:
gomock
)Пример с интерфейсом:
type Storage interface {
Get(id int) (string, error)
}
func Process(s Storage, id int) (string, error) {
data, err := s.Get(id)
if err != nil {
return "", err
}
return "Processed: " + data, nil
}
Тест с моком:
type mockStorage struct {
data string
err error
}
func (m *mockStorage) Get(id int) (string, error) {
return m.data, m.err
}
func TestProcess(t *testing.T) {
tests := []struct {
name string
data string
err error
expected string
wantErr bool
}{
{"success", "test", nil, "Processed: test", false},
{"error", "", errors.New("not found"), "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
storage := &mockStorage{data: tt.data, err: tt.err}
got, err := Process(storage, 1)
if (err != nil) != tt.wantErr {
t.Fatalf("unexpected error: %v", err)
}
if got != tt.expected {
t.Errorf("got %q, want %q", got, tt.expected)
}
})
}
}
Test[Функция]_[Сценарий]
Unit-тесты в Go — это:
testing
Хорошие unit-тесты экономят время на отладку, предотвращают регрессии и служат живой документацией к коду.