Go: как запускать тесты для нескольких пакетов?

У меня есть несколько пакетов под подкаталог под src/, запуск тестов для каждого пакета с помощью go test работает нормально.

При попытке запустить все тесты с помощью go test ./... тесты выполняются, но это не удается.

тесты выполняются на локальных серверах баз данных, каждый тестовый файл имеет глобальные переменные с указателями db.

Я попытался запустить тесты с помощью -parallel 1, чтобы предотвратить конфликт в db, но тесты все еще терпят неудачу.

что может быть здесь?

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

ИЗМЕНИТЬ 2:

каждый из моих тестовых файлов имеет две глобальные переменные (используя mgo):

var session *mgo.Session
var db *mgo.Database

также имеет следующие функции настройки и разблокировки:

func setUp() {
   s, err := cfg.GetDBSession()
   if err != nil {
       panic(err)
   }

   session = s

   db = cfg.GetDB(session)

   db.DropDatabase()
}

func tearDown() {
   db.DropDatabase()

   session.Close()
}

каждый запуск тестов с setUp() и defer tearDown()

также cfg:

package cfg

import (
    "labix.org/v2/mgo"
)

func GetDBSession() (*mgo.Session, error) {
    session, err := mgo.Dial("localhost")

    return session, err
}

func GetDB(session *mgo.Session) *mgo.Database {
    return session.DB("test_db")
}

ИЗМЕНИТЬ 3:

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

можно ли заставить go test запускать все последовательно по пакетам?

Ответ 1

очевидно, работает go test -p 1 работает последовательно (включая сборку), я не вижу этого аргумента в go help test или go help testflag

Ответ 2

Обновление. Как отметил @Gal Ben-Haim, добавление флага (недокументированных) go test -p 1 выполняется и проверяет все пакеты в последовательном порядке. Как указано в сообщении об использовании testflag в исходном коде Go:

-p = n: строить и тестировать до n пакетов параллельно

Старый ответ:

При запуске go test ./... тесты разных пакетов фактически выполняются параллельно, даже если вы устанавливаете parallel=1 (только тесты в определенном пакете гарантированно запускаются по одному). Если важно, чтобы пакеты были протестированы последовательно, например, когда есть настройка базы данных/разрывы, кажется, что единственный способ прямо сейчас - использовать оболочку для эмуляции поведения go test ./... и принуждения пакетов к протестированы один за другим.

Что-то вроде этого, например, работает в Bash:

find . -name '*.go' -printf '%h\n' | sort -u | xargs -n1 -P1 go test

Сначала команда перечисляет все подкаталоги, содержащие *.go файлы. Затем он использует sort -u, чтобы перечислить каждый подкаталог только один раз (удаление дубликатов). Наконец, все подкаталоги, содержащие файлы go, передаются на go test через xargs. -P1 указывает, что должна выполняться не более одной команды за раз.

К сожалению, это намного уродливее, чем просто запуск go test ./..., но он может быть приемлемым, если он помещается в оболочку script или сглаживается в функцию, которая более запоминается:

function gotest(){   find $1 -name '*.go' -printf '%h\n' | sort -u | xargs -n1 -P1 go test; }

Теперь все тесты можно запустить в текущем каталоге, вызвав:

gotest .

Ответ 3

Я предполагаю, что, поскольку пакеты индивидуально передают, что в этой ситуации вы также отбрасываете БД еще до этого теста.

Поэтому кажется, что состояние БД для каждого теста пакета должно быть пустым.
Поэтому между каждым набором тестов пакета БД должна быть опустошена. Есть два способа обойти это, не зная всей вашей ситуации. Я кратко объясню оба варианта:

Вариант 1. Настройка тестирования

Добавьте функцию init() в начало каждого пакета _test файла, который затем выложили для удаления БД. Это будет выполняться до метода init() фактического пакета:

func init() {
    fmt.Println("INIT TEST")
    // My test state initialization
    // Remove database contents
}

Предполагая, что в пакете также была аналогичная строка печати, которую вы увидели бы на выходе (обратите внимание, что вывод stdout отображается только тогда, когда тест завершился с ошибкой или вы предоставили опцию -v)

INIT TEST
INIT PACKAGE

Вариант 2. Макет базы данных

Создайте макет для базы данных (если только это не то, что вы тестируете). Фальшивый db всегда может действовать так же, как DB пуст для начального состояния каждого теста.

Ответ 4

Попробуйте использовать следующий репозиторий github.

https://github.com/appleboy/golang-testing

Скопируйте coverage.sh в /usr/local/bin/coverage и измените разрешение.

$ curl -fsSL https://raw.githubusercontent.com/appleboy/golang-testing/master/coverage.sh /usr/local/bin/coverage
$ chmod +x /usr/local/bin/coverage