首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Golang测试中的Fixtures

Golang测试中的Fixtures
EN

Stack Overflow用户
提问于 2016-01-20 08:59:21
回答 3查看 6.5K关注 0票数 10

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

EN

回答 3

Stack Overflow用户

发布于 2016-01-26 00:42:43

如果你想使用标准的Go测试工具,你可以定义一个带有签名TestMain(m *testing.M)的函数,并把你的fixture代码放在里面。

testing package wiki

测试程序有时需要在测试之前或之后执行额外的设置或拆卸。测试有时也有必要控制哪些代码在主线程上运行。为了支持这些和其他情况,如果测试文件包含函数:

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()) }

票数 9
EN

Stack Overflow用户

发布于 2018-10-08 22:16:47

我知道这是一个古老的问题,但这仍然出现在搜索结果中,所以我想我应该给出一个可能的答案。

您可以将代码隔离到辅助函数中,这些辅助函数返回一个"teardown“函数,以便在其自身之后进行清理。以下是启动服务器并在测试用例结束时将其关闭的一种可能方法。

代码语言:javascript
复制
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以及一个充当“teardown”的函数。此函数被添加到延迟堆栈中,因此无论测试用例如何退出,都会始终调用它。

如果你有一个更复杂的设置,并且你需要处理错误,你可以选择传入*testing.T。这个例子展示了设置函数返回一个*url.URL而不是URL格式的字符串,解析可能会返回一个错误。

代码语言:javascript
复制
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)
}
票数 6
EN

Stack Overflow用户

发布于 2021-08-27 23:00:21

我为use fixtures编写了类似于pytest的golang引擎:https://github.com/rekby/fixenv

使用示例:

代码语言:javascript
复制
package example

// db create database abd db struct, cached per package - call
// once and same db shared with all tests
func 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
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34889721

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档