Несколько слов о запуске Go-тестов

Рассмотрим в качестве примера простой проект на Go, его структура описана ниже:

example
├── cmd
│   └── main.go
├── go.mod
├── go.sum
└── pkg
    ├── bar
    │   ├── bar.go
    │   └── bar_test.go
    └── foo
        ├── foo.go
        └── foo_test.go

4 directories, 7 files

Заметим, что в пакетах foo и bar присутствуют тесты, попробуем запустить их из корня командой go test ./...:

?       example/cmd [no test files]
ok      example/pkg/bar 0.006s
ok      example/pkg/foo 0.005s

В процессе работы go test ./...рекурсивно обходит нашу папку и запускает все тесты, которые найдет. Это особенно удобно при использовании с CI — нам нужно добавить лишь одну строку в конфигурацию.

Может показаться, что тесты выполняются последовательно, друг за другом. При использовании дефолтных настроек это не так. Проверим — внесем следующие изменения в код:

func TestNewBar(t *testing.T) {
        log.Printf("bar test start time: %v", time.Now())
        time.Sleep(time.Second)
        bar := NewBar(100)
        require.Equal(t, 101, bar.Size)
}

func TestNewFoo(t *testing.T) {
        log.Printf("foo test start time: %v", time.Now())
        time.Sleep(time.Second)
        foo := NewFoo(100)
        require.Equal(t, 101, foo.Size)
}

Для каждого теста мы добавили печать времени запуска, задержку в секунду и плюс сделали так, чтобы они гарантированно не проходили. Повторим запуск:

?       example/cmd [no test files]
2020/07/18 12:50:54 bar test start time: 2020-07-18 12:50:54.079533681 +0700 +07 m=+0.001231839
--- FAIL: TestNewBar (1.00s)
    bar_test.go:15: 
            Error Trace:    bar_test.go:15
            Error:          Not equal: 
                            expected: 101
                            actual  : 100
            Test:           TestNewBar
FAIL
FAIL    example/pkg/bar 1.006s
2020/07/18 12:50:54 foo test start time: 2020-07-18 12:50:54.079717636 +0700 +07 m=+0.001206226
--- FAIL: TestNewFoo (1.00s)
    foo_test.go:15: 
            Error Trace:    foo_test.go:15
            Error:          Not equal: 
                            expected: 101
                            actual  : 100
            Test:           TestNewFoo
FAIL
FAIL    example/pkg/foo 1.005s
FAIL

Обратите внимание на времена, которые мы логируем — они практически одинаковые, что подтверждает нашу теорию.

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

Для особенно заинтересовавшихся темой оставляю ссылку на исходных код запуска тестов, в котором можно найти все детали: [https://golang.org/src/cmd/go/internal/work/exec.go?s=981:1015#L46](https://golang.org/src/cmd/go/internal/work/exec.go?s=981:1015#L46).