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 關注
- 144 瀏覽
添加回答
舉報