-
湖上湖
Go 基于强大的包管理,这意味着命名空间被视为一个文件。如果establish_db_connection在单个测试包中使用,它可以以小写字母开头表示私有实例,并在测试文件中使用与被测试代码相同的包(注意 Go 中的命名约定是establishDBConnection)。但是,大多数时候,就像在data/sql中一样,您会希望获得一次数据库连接并保持它直到测试完成(更像是工厂和注入模式)。标准testing包中没有。如果你喜欢 BDD,Goconvey使用范围来定义固定装置和reset用于拆卸的函数。您可以在测试中使用工厂和依赖注入。我认为这很地道。一些包括Goconvey,Ginkgo和Testify他们都有自己的优点和缺点。前两个通常以太多的嵌套范围结束,但 Goconvey 有一个很棒的基于浏览器的实时测试服务器,可以与 Go 标准测试一起使用。由于 Go 中没有全局变量/函数,因此您可以以接口委托模式设计项目,以帮助跨包导入函数并在处理跨包测试时避免循环导入。mypackagetype DBOptions struct { Name, Credentials string}func aFunc(db *sql.DB) error { // do something return nil}func bFunc(db *sql.DB) int, error { // do something return 0, nil}func establishConn(opts *DBOptions) (*sql.DB, error) { db, err := sql.Open(opts.Name, opts.Credentials) if err != nil { return nil, err } return db, nil}func destroyConn(conn *sql.DB) { conn.Close()}// test filemypackage import "testing"var myOpt = &DBOptions{ Name: "mysql", Credentials: "user:password@tcp(127.0.0.1:3306)/hello",}var conn, _ = establishConn(myOpt)func TestAFunc(t *testing.T) { err := aFunc(conn) if err != nil { t.Error(err) }}func TestBFunc(t *testing.T) { err := aFunc(conn) if err != nil { t.Error(err) }}// use `conn` in other tests ...destroyConn(conn)
-
www说
关于 Rails 中类似 FactoryGirl 的测试夹具库,go 中有一些选择。这两个图书馆得到的明星最多。https://github.com/bluele/factory-gohttps://github.com/go-testfixtures/testfixtures而且我还实现了与上述库相比类型安全、干燥且灵活的测试夹具库!https://github.com/k-yomo/fixtory
-
潇潇雨雨
在夹具上:考虑在您的测试用例中传递函数:package mainimport "testing"type testcase struct { scenario string before func(string) after func() input string expOutput string}var state = ""func setup(s string) { state = s}func nilSetup(s string) {}func reset() { state = ""}func execute(s string) string { return state}func TestSetupTeardown(t *testing.T) { tcs := []testcase{ { scenario: "blank output when initial state is wrong", before: nilSetup, after: reset, input: "foo", expOutput: "", }, { scenario: "correct output when initial state is right", before: setup, after: reset, input: "foo", expOutput: "foo", }, } for _, tc := range tcs { tc.before(tc.input) if out := execute(tc.input); out != tc.expOutput { t.Fatal(tc.scenario) } tc.after() }}