Go: как запустить тесты для нескольких пакетов?
У меня есть несколько пакетов в подкаталоге в каталоге src/, и я запускаю тесты для каждого пакета с go test
работает нормально.
При попытке запустить все тесты с go test ./...
тесты запущены, но не удается..
тесты выполняются на локальных серверах баз данных, каждый тестовый файл имеет глобальные переменные с указателями db.
Я пытался запустить тесты с -parallel 1
для предотвращения раздоров в БД, но тесты все равно не пройдены.
в чем может быть проблема здесь?
РЕДАКТИРОВАТЬ: некоторые тесты не проходят на отсутствующих записях БД, я полностью очищаю БД до и после каждого теста. единственная причина, по которой я могу подумать, почему это происходит, из-за некоторого раздора между тестами.
РЕДАКТИРОВАТЬ 2:
каждый из моих тестовых файлов имеет 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
запустить все последовательно через пакеты?
5 ответов
По -видимому, работает go test -p 1
запускает все последовательно (включая сборку), я не вижу этого аргумента в go help test
или же go help testflag
Обновление: как отметил @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 ./...
, но это может быть приемлемо, если его поместить в сценарий оболочки или добавить в псевдоним функцию, которая более запоминаема:
function gotest(){ find $1 -name '*.go' -printf '%h\n' | sort -u | xargs -n1 -P1 go test; }
Теперь все тесты можно запустить в текущем каталоге, вызвав:
gotest .
Я предполагаю, что поскольку пакеты по отдельности проходят, то в этой ситуации вы также отбрасываете БД перед этим тестом.
Поэтому похоже, что состояние БД для каждого теста пакета должно быть пустым.
Таким образом, между каждым набором тестов пакета БД должна быть очищена. Есть два пути, не зная всей вашей ситуации, я кратко объясню оба варианта:
Вариант 1. Настройка теста
Добавить init()
Функция начала каждого пакета _test файл, который вы затем помещаете обработку для удаления БД. Это будет выполнено до init()
метод фактической упаковки:
func init() {
fmt.Println("INIT TEST")
// My test state initialization
// Remove database contents
}
Предполагая, что пакет также имеет аналогичную строку печати, которую вы увидите в выходных данных (обратите внимание, что вывод stdout отображается только в случае сбоя теста или если вы указали -v
опция)
INIT TEST
INIT PACKAGE
Вариант 2. Макет базы данных
Создайте макет для базы данных (если только это не то, что вы тестируете). Макет БД всегда может вести себя так, будто БД пуста для начального состояния каждого теста.
Я использовал дешевый способ собирать тесты в несколько пакетов.
go test -v ./... -run "TestUnit?"
Просто назовите свои тесты, чтобы их поймали:
func TestUnitCountriesStructs(t *testing.T)
Вы упомянули о необходимости какой-то настройки и демонтажа для ваших тестов. Я использую свидетельствовать. Суммируя:
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
}
// before each test
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
}
func (suite *ExampleTestSuite) TestExample() {
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
suite.Equal(5, suite.VariableThatShouldStartAtFive)
}
func TestUnitExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
}
Пожалуйста, попробуйте следующий 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