3 回答
TA贡献2003条经验 获得超2个赞
Go 基于强大的包管理,这意味着命名空间被视为一个文件。如果establish_db_connection在单个测试包中使用,它可以以小写字母开头表示私有实例,并在测试文件中使用与被测试代码相同的包(注意 Go 中的命名约定是establishDBConnection)。但是,大多数时候,就像在data/sql中一样,您会希望获得一次数据库连接并保持它直到测试完成(更像是工厂和注入模式)。
标准testing包中没有。如果你喜欢 BDD,Goconvey使用范围来定义固定装置和reset用于拆卸的函数。
您可以在测试中使用工厂和依赖注入。我认为这很地道。
一些包括Goconvey,Ginkgo和Testify他们都有自己的优点和缺点。前两个通常以太多的嵌套范围结束,但 Goconvey 有一个很棒的基于浏览器的实时测试服务器,可以与 Go 标准测试一起使用。
由于 Go 中没有全局变量/函数,因此您可以以接口委托模式设计项目,以帮助跨包导入函数并在处理跨包测试时避免循环导入。
mypackage
type 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 file
mypackage
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)
TA贡献1775条经验 获得超8个赞
关于 Rails 中类似 FactoryGirl 的测试夹具库,go 中有一些选择。
这两个图书馆得到的明星最多。
而且我还实现了与上述库相比类型安全、干燥且灵活的测试夹具库!
TA贡献1833条经验 获得超4个赞
在夹具上:考虑在您的测试用例中传递函数:
package main
import "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()
}
}
- 3 回答
- 0 关注
- 126 浏览
添加回答
举报