15

我在 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跨包按顺序运行所有内容?

4

4 回答 4

21

更新:正如@Gal Ben-Haim 所指出的,添加(未记录的)go test -p 1标志会以串行方式构建和测试所有包。正如 Go 源代码中的 testflag 使用消息所说:

-p=n:并行构建和测试最多 n 个包

旧答案

运行时go test ./...,不同包的测试实际上是并行运行的,即使您设置parallel=1了(只有特定包中的测试保证一次运行一个)。如果按顺序测试包很重要,比如涉及数据库设置/拆卸时,现在似乎唯一的方法是使用 shell 来模拟 的行为go test ./...,并强制测试一个包一。

例如,像这样的东西在 Bash 中有效:

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

该命令首先列出所有包含*.go文件的子目录。然后它只sort -u列出每个子目录一次(删除重复项)。最后,所有包含 go 文件的子目录都被输入go testvia xargs-P1表示一次最多运行一个命令。

不幸的是,这比运行要丑得多go test ./...,但如果将其放入 shell 脚本或别名为更容易记住的函数,这可能是可以接受的:

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

现在可以通过调用在当前目录中运行所有测试:

gotest .
于 2014-05-24T03:00:39.937 回答
12

显然运行go test -p 1顺序运行所有内容(包括构建),我没有看到这个论点go help testgo help testflag

于 2014-05-24T08:13:40.823 回答
0

我假设因为包单独通过,在这种情况下,你也在测试之前删除了数据库。

因此,听起来每个包测试的数据库状态都应该是空的。
因此,在每组包测试之间,必须清空数据库。有两种方法可以解决这个问题,不了解您的全部情况,我将简要解释这两种选择:

选项 1. 测试设置

在每个包 _test 文件的开头添加一个init()函数,然后将其处理以删除数据库。这将init()在实际包的方法之前运行:

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

假设该包也有一个类似的打印行,您会在输出中看到(注意 stdout 输出仅在 a 测试失败或您提供-v选项时显示)

INIT TEST
INIT PACKAGE

选项 2. 模拟数据库

为数据库创建一个模拟(除非这是您正在测试的具体内容)。对于每个测试的起始状态,模拟数据库总是可以表现得就像数据库是空白的一样。

于 2014-05-19T01:46:28.910 回答
-1

请尝试以下 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
于 2016-07-30T12:37:08.563 回答