猿问

Golang 测试中的夹具

来自 python 世界,fixtures 非常有用(Fixtures 为可重用状态/支持逻辑定义了一个 Python 契约,主要用于单元测试)。我想知道 Golang 是否有类似的支持,它可以让我使用一些预定义的装置来运行我的测试,比如设置服务器,拆除它,每次运行测试时都做一些重复的任务?有人可以指出我在 Golang 中做同样事情的一些例子吗?


白衣非少年
浏览 152回答 3
3回答

繁星coding

如果你想使用标准的 Go 测试工具,你可以定义一个带有签名的函数TestMain(m *testing.M)并将你的夹具代码放在那里。从测试包维基:有时,测试程序需要在测试之前或之后进行额外的设置或拆卸。有时也需要测试来控制哪些代码在主线程上运行。为了支持这些和其他情况,如果测试文件包含一个函数:func TestMain(m *testing.M)那么生成的测试将调用 TestMain(m) 而不是直接运行测试。TestMain 运行在主 goroutine 中,并且可以围绕对 m.Run 的调用进行任何必要的设置和拆卸。然后它应该使用 m.Run 的结果调用 os.Exit。调用 TestMain 时,flag.Parse 尚未运行。如果 TestMain 依赖于命令行标志,包括测试包的那些,它应该显式调用 flag.Parse。TestMain 的一个简单实现是:func TestMain(m *testing.M) {    flag.Parse()    os.Exit(m.Run())}

一只名叫tom的猫

我知道这是一个老问题,但这仍然出现在搜索结果中,所以我想我会给出一个可能的答案。您可以将代码隔离到辅助函数中,这些辅助函数返回一个“拆卸”函数以在其自身之后进行清理。这是启动服务器并在测试用例结束时关闭它的一种可能方法。func setUpServer() (string, func()) {    h := func(w http.ResponseWriter, r *http.Request) {        code := http.StatusTeapot        http.Error(w, http.StatusText(code), code)    }    ts := httptest.NewServer(http.HandlerFunc(h))    return ts.URL, ts.Close}func TestWithServer(t *testing.T) {    u, close := setUpServer()    defer close()    rsp, err := http.Get(u)    assert.Nil(t, err)    assert.Equal(t, http.StatusTeapot, rsp.StatusCode)}这将启动一个服务器net/http/httptest并返回它的 URL 以及一个充当“拆卸”的函数。这个函数被添加到 defer 堆栈中,因此无论测试用例如何退出,它总是被调用。或者,*testing.T如果您有更复杂的设置并且需要处理错误,您可以传入。此示例显示设置函数返回一个*url.URL而不是 URL 格式的字符串,并且解析可能会返回一个错误。func setUpServer(t *testing.T) (*url.URL, func()) {    h := func(w http.ResponseWriter, r *http.Request) {        code := http.StatusTeapot        http.Error(w, http.StatusText(code), code)    }    ts := httptest.NewServer(http.HandlerFunc(h))    u, err := url.Parse(ts.URL)    assert.Nil(t, err)    return u, ts.Close}func TestWithServer(t *testing.T) {    u, close := setUpServer(t)    defer close()    u.Path = "/a/b/c/d"    rsp, err := http.Get(u.String())    assert.Nil(t, err)    assert.Equal(t, http.StatusTeapot, rsp.StatusCode)}

沧海一幻觉

我写了golang引擎来使用类似于pytest的fixtures:https : //github.com/rekby/fixenv用法示例:package example// db create database abd db struct, cached per package - call// once and same db shared with all testsfunc db(e Env)*DB{...}// DbCustomer - create customer with random personal data// but fixed name. Fixture result shared by test and subtests, // then mean many calls Customer with same name will return same// customer object.// Call Customer with other name will create new customer// and resurn other object.func DbCustomer(e Env, name string) Customer {    // ... create customer    db(e).CustomerStore(cust)    // ...    return cust}// DbAccount create bank account for customer with given name.func DbAccount(e Env, customerName, accountName string)Account{    cust := DbCustomer(e, customerName)    // ... create account    db(e).AccountStore(acc)    // ...    return acc}func TestFirstOwnAccounts(t *testing.T){    e := NewEnv(t)    // background:    // create database    // create customer bob     // create account from    accFrom := DbAccount(e, "bob", "from")        // get existed db, get existed bob, create account to    accTo := DbAccount(e, "bob", "to")        PutMoney(accFrom, 100)    SendMoney(accFrom, accTo, 20)    if accFrom != 80 {        t.Error()    }    if accTo != 20 {        t.Error()       }        // background:    // delete account to    // delete account from    // delete customer bob}func TestSecondTransferBetweenCustomers(t *testing.T){    e := NewEnv(t)        // background:    // get db, existed from prev test    // create customer bob    // create account main for bob    accFrom := DbAccount(e, "bob", "main")        // background:    // get existed db    // create customer alice    // create account main for alice    accTo := DbAccount(e, "alice", "main")    PutMoney(accFrom, 100)    SendMoney(accFrom, accTo, 20)    if accFrom != 80 {        t.Error()    }    if accTo != 20 {        t.Error()    }        // background:    // remove account of alice    // remove customer alice    // remove account of bob    // remove customer bob}// background:// after all test finished drop database
随时随地看视频慕课网APP

相关分类

Go
我要回答