Тестирование и бенчмаркирование

Beginner

This tutorial is from open-source community. Access the source code

Введение

Этот лабораторный практикум旨在演示单元测试和基准测试在编写规范的 Go 程序中的重要性。testing包提供了编写单元测试所需的工具,而go test命令则用于运行测试。

Тестирование и бенчмаркирование

Проблема, которую необходимо решить в этом лабораторном практикуме, — это протестировать и провести бенчмарк простой реализации функции нахождения минимального целого числа под названием IntMin.

  • Необходимо импортировать пакет testing.
  • Функция IntMin должна принимать два целочисленных параметра и возвращать целое число.
  • Функция TestIntMinBasic должна тестировать функцию IntMin для базовых значений входных данных.
  • Функция TestIntMinTableDriven должна тестировать функцию IntMin в табличном стиле.
  • Функция BenchmarkIntMin должна провести бенчмарк функции IntMin.
## Запустить все тесты в текущем проекте в подробном режиме.

## Запустить все бенчмарки в текущем проекте. Все тесты
## выполняются перед бенчмарками. Флаг `bench` фильтрует
## имена функций бенчмарков с помощью регулярного выражения.

Ниже представлен полный код:

// Юнит-тестирование является важной частью написания
// принципиальных Go-программ. Пакет `testing`
// предоставляет инструменты, которые нам нужны для написания
// юнит-тестов, а команда `go test` запускает тесты.

// В целях демонстрации этот код находится в пакете
// `main`, но это может быть любой пакет. Код для тестирования
// обычно находится в том же пакете, что и код, который он тестирует.
package main

import (
    "fmt"
    "testing"
)

// Мы будем тестировать эту простую реализацию
// нахождения минимального целого числа. Обычно код,
// который мы тестируем, находится в исходном файле,
// названном, например, `intutils.go`, а тестовый файл
// для него будет называться `intutils_test.go`.
func IntMin(a, b int) int {
    if a < b {
        return a
    }
    return b
}

// Тест создается путем написания функции с именем,
// начинающимся с `Test`.
func TestIntMinBasic(t *testing.T) {
    ans := IntMin(2, -2)
    if ans!= -2 {
        // `t.Error*` сообщит о неудаче теста, но продолжит
        // выполнение теста. `t.Fatal*` сообщит о неудаче теста
        // и немедленно остановит тест.
        t.Errorf("IntMin(2, -2) = %d; want -2", ans)
    }
}

// Пишение тестов может быть повторяющимся процессом, поэтому
// обычно используется *табличный стиль*, где входные данные
// теста и ожидаемые выходные данные перечислены в таблице,
// и единственный цикл проходит по ним и выполняет логику теста.
func TestIntMinTableDriven(t *testing.T) {
    var tests = []struct {
        a, b int
        want int
    }{
        {0, 1, 0},
        {1, 0, 0},
        {2, -2, -2},
        {0, -1, -1},
        {-1, 0, -1},
    }

    for _, tt := range tests {
        // t.Run позволяет запускать "подтесты", по одному для
        // каждой записи таблицы. Они отображаются отдельно
        // при выполнении `go test -v`.
        testname := fmt.Sprintf("%d,%d", tt.a, tt.b)
        t.Run(testname, func(t *testing.T) {
            ans := IntMin(tt.a, tt.b)
            if ans!= tt.want {
                t.Errorf("got %d, want %d", ans, tt.want)
            }
        })
    }
}

// Бенчмарк-тесты обычно находятся в файлах `_test.go` и
// именуются с префиксом `Benchmark`. Выполняющийся тестер
// несколько раз запускает каждую функцию бенчмарка,
// увеличивая `b.N` на каждой итерации, пока не получит
// точную меру.
func BenchmarkIntMin(b *testing.B) {
    // Обычно бенчмарк запускает функцию, которую мы
    // бенчмаркируем, в цикле `b.N` раз.
    for i := 0; i < b.N; i++ {
        IntMin(1, 2)
    }
}

Резюме

Этот лабораторный практикум показал, как писать юнит-тесты и функции бенчмарка с использованием пакета testing в Go. Функция TestIntMinBasic тестировала функцию IntMin для базовых значений входных данных, в то время как функция TestIntMinTableDriven использовала табличный стиль для тестирования функции IntMin. Функция BenchmarkIntMin провела бенчмарк функции IntMin, чтобы измерить ее производительность.