Расскажите об основах тестирования в Go. Как писать юнит-тесты, табличные тесты и бенчмарки?

Ответ

Тестирование — это встроенная и первоклассная возможность языка Go, для которой используется стандартный пакет testing и утилита go test.

Основные правила:

  1. Тесты находятся в файлах с суффиксом _test.go.
  2. Тестовые файлы располагаются в том же пакете, что и тестируемый код.
  3. Тестовая функция должна начинаться с Test, принимать один аргумент t *testing.T и не возвращать значений.

1. Простой юнит-тест:

// В файле sum.go
func Sum(a, b int) int {
    return a + b
}

// В файле sum_test.go
func TestSum(t *testing.T) {
    got := Sum(2, 3)
    want := 5
    if got != want {
        t.Errorf("Sum(2, 3) = %d; want %d", got, want)
    }
}

2. Табличные тесты (Table-Driven Tests):
Это идиоматичный и предпочтительный способ для проверки множества кейсов. Для изоляции тестов и более четкого вывода используется t.Run().

func TestSumTable(t *testing.T) {
    tests := []struct {
        name string // Имя под-теста
        a    int
        b    int
        want int
    }{
        {"positive numbers", 1, 2, 3},
        {"zeroes", 0, 0, 0},
        {"negative and positive", -1, 1, 0},
        {"negative numbers", -2, -3, -5},
    }

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

3. Бенчмарки (Benchmarks):
Для измерения производительности. Функция должна начинаться с Benchmark и принимать *testing.B.

func BenchmarkSum(b *testing.B) {
    // b.N - это количество итераций, которое определяет сам фреймворк
    for i := 0; i < b.N; i++ {
        Sum(100, 200)
    }
}

Запуск тестов:

  • go test: запуск всех тестов в текущем пакете.
  • go test -v: запуск с подробным выводом, включая имена запущенных тестов.
  • go test ./...: запуск тестов во всех под-пакетах.
  • go test -run TestSumTable/zeroes: запуск конкретного под-теста.
  • go test -cover: показать покрытие кода тестами.
  • go test -bench .: запуск всех бенчмарков.