Перейти к основному содержимому

Тестирование в Go

Разработчику Архитектору

Тестирование в Go

Пакет testing в стандартной библиотеке — основа. Идиоматичный стиль — table-driven tests. Для HTTP — net/http/httptest, для удобных assert — testify.

База: Первая программа на Go · Справочник по Go · Фреймворки.


Именование и запуск

Файл: greeting_test.go в том же пакете, что и код.

package greeting

import "testing"

func TestHello(t *testing.T) {
got := Hello("Go")
want := "Hello, Go!"
if got != want {
t.Errorf("Hello() = %q, want %q", got, want)
}
}
go test ./...
go test -v ./pkg/greeting
go test -cover ./...

Table-driven tests

func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
want int
}{
{"zeros", 0, 0, 0},
{"positive", 2, 3, 5},
{"negative", -1, 1, 0},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Add(tt.a, tt.b); got != tt.want {
t.Errorf("got %d, want %d", got, tt.want)
}
})
}
}

t.Run даёт изолированные подтесты в отчёте.


testify

go get github.com/stretchr/testify
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestHelloAssert(t *testing.T) {
assert.Equal(t, "Hi, Ann", Hello("Ann"))
require.NotEmpty(t, Hello("x")) // require останавливает тест при провале
}

HTTP handler (httptest)

func TestHealthHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/health", nil)
rec := httptest.NewRecorder()

HealthHandler(rec, req)

assert.Equal(t, http.StatusOK, rec.Code)
assert.Contains(t, rec.Body.String(), "ok")
}

Для Gin: router := gin.New(); router.ServeHTTP(rec, req).


Моки интерфейсов

Go не имеет встроенных моков — используют интерфейсы и ручные fake:

type UserStore interface {
Save(name string) error
}

type fakeStore struct {
saved []string
}

func (f *fakeStore) Save(name string) error {
f.saved = append(f.saved, name)
return nil
}

func TestService_Register(t *testing.T) {
store := &fakeStore{}
svc := NewService(store)
require.NoError(t, svc.Register("Ann"))
assert.Equal(t, []string{"Ann"}, store.saved)
}

Генераторы: mockgen (gomock), moq — для крупных проектов.


Benchmark

func BenchmarkHello(b *testing.B) {
for i := 0; i < b.N; i++ {
Hello("bench")
}
}
go test -bench=. -benchmem ./...

CI

- uses: actions/setup-go@v5
with:
go-version: '1.22'
- run: go test -race -coverprofile=coverage.out ./...

Флаг -race включает детектор гонок данных.


Связанные материалы


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).