Как в Go пишут unit тесты со стандартным пакетом testing

Стандартный пакет `testing` предоставляет инструменты для написания и выполнения юнит-тестов. Давайте рассмотрим, как писать юнит-тесты с использованием этого пакета.

Основные компоненты 

1. Тестовые файлы:

  • Должны иметь суффикс `_test.go`. Это позволяет инструменту тестирования Go автоматически распознавать их как тестовые файлы.

2. Тестовые функции:

  • Должны начинаться с `Test` и принимать один аргумент типа `*testing.T`. Это соглашение позволяет инструменту тестирования Go идентифицировать их как тестовые функции.

Пример простого теста

```go
// main.go
package main

func Add(a, b int) int {
    return a + b
}
```
```go
// main_test.go
package main

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5
    if result != expected {
        t.Errorf("Add(2, 3) = %d; want %d", result, expected)
    }
}
```

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

Чтобы это сделать, выполните команду `go test` в терминале. Эта команда автоматически найдет и выполнит все тесты в текущем пакете.

```sh
$ go test
```

Тестирование с таблицей (table-driven tests)

Это подход, при котором вы пишете тесты в виде таблицы входных и ожидаемых значений. Это улучшает читаемость и позволяет легко добавлять новые тестовые случаи.

```go
// main_test.go
package main

import "testing"

func TestAdd(t *testing.T) {
    tests := []struct {
        a, b, expected int
    }{
        {1, 2, 3},
        {0, 0, 0},
        {-1, -1, -2},
        {2, 2, 4},
    }

    for _, tt := range tests {
        result := Add(tt.a, tt.b)
        if result != tt.expected {
            t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected)
        }
    }
}
```

Бенчмаркинг

Для измерения производительности кода используйте функции, начинающиеся с `Benchmark` и принимающие `*testing.B`.

```go
// main_test.go
package main

import "testing"

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(2, 3)
    }
}
```

Примерные тесты (Example Tests)

```go
// main.go
package main

import "fmt"

func ExampleAdd() {
    fmt.Println(Add(2, 3))
    // Output: 5
}
```

Лучшие практики написания данных тестов

1. Соблюдайте атомарность:

  • Каждый юнит-тест должен проверять только одну конкретную функцию или метод и проверять один аспект её поведения.

2. Используйте понятные названия:

  • Имена тестовых функций должны быть понятными и отражать их цель. Например, `TestAdd` для тестирования функции `Add`.

3. Проверяйте крайние случаи:

  • Убедитесь, что ваши тесты проверяют крайние случаи и потенциальные ошибки, такие как нулевые значения, отрицательные числа и переполнения.

4. Регулярно запускайте тесты:

  • Особенно перед коммитами и релизами, чтобы убедиться в отсутствии регрессий.

5. Используйте mocking, если необходимо:

  • При тестировании функций, которые зависят от внешних ресурсов (таких как базы данных или API), используйте мокирование (mocking) для изоляции тестов.

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

1. Запуск всех тестов с подробным выводом:

   ```sh
   $ go test -v
   ```

2. Запуск бенчмарков:

   ```sh
   $ go test -bench=.
   ```

3. Покрытие кода:

  • Чтобы увидеть покрытие тестами, используйте флаг `-cover`.
   ```sh
   $ go test -cover
   ```

Юнит-тесты пишутся в файлах с суффиксом `_test.go` и выполняются с помощью команды `go test`. Они проверяют отдельные функции или методы, чтобы убедиться, что они работают корректно. Пакет `testing` предоставляет все необходимые инструменты для написания и выполнения тестов, бенчмарков и примерных тестов.

June 2, 2024, easyoffer

Примеры ответов: