Go:如何为多个包运行测试?

时间:2014-05-17 19:31:48

标签: unit-testing go mgo

我在src /下的子目录下有多个包, 使用go test运行每个包的测试工作正常。

当尝试使用go test ./...运行所有测试时,测试正在运行,但它失败了..

测试针对本地数据库服务器运行,每个测试文件都有带有数据库指针的全局变量。

我尝试使用-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 个答案:

答案 0 :(得分:19)

更新:正如@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 test被送到xargs-P1表示一次最多只能运行一个命令。

不幸的是,这比运行go test ./...更加丑陋,但如果将它放入shell脚本或别名成为更难忘的函数,则可能是可以接受的:

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

现在可以通过调用:

在当前目录中运行所有测试
gotest .

答案 1 :(得分:11)

显然正在运行go test -p 1按顺序运行所有内容(包括构建),我在go help testgo help testflag

中看不到此参数

答案 2 :(得分:0)

我假设因为在这种情况下你的包也会单独传递,你也会在测试之前删除数据库。

因此,听起来每个包测试的DB状态都是空的 因此,在每组包测试之间,必须清空DB。有两种解决方法,不知道你的整个情况,我将简要解释两种选择:

选项1.测试设置

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

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

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

INIT TEST
INIT PACKAGE

选项2.模拟数据库

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

答案 3 :(得分:0)

请试用以下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