为了账号安全,请及时绑定邮箱和手机立即绑定

Golang 测试中可重用的组件和固定装置

Golang 测试中可重用的组件和固定装置

Go
RISEBY 2022-01-17 10:20:43
我刚刚开始使用 Golang 并编写我的第一个测试套件。我有 Rails 的背景,它为测试工具(Rspec、Cucumber 等)提供了极好的支持,所以我正在以类似的心态进行我的 golang 测试(不确定这是对还是错)我有一个User数据模型(基本上是一个结构),它从 postgres 中的表中读取记录users并存储它们的数组。(本质上是 ActiveRecord 在 Rails 世界中所做的一个非常简单的版本)我想编写一个测试来检查例程是否正确地从数据库中读取并构建模型。在几乎每个测试套件中,我都会连接到数据库,所以我有一个名为establish_db_connection. 我可以把它放在哪里,以便我的所有测试集中使用它?建立 #1 - 是否有等效的before块或某些设置/拆卸方法,我可以在每次测试之前建立连接?最后,我如何处理固定装置?现在在每次测试之前,我都会调用一个clear_db函数来重置所有表并插入一些静态数据行。我很想摆脱固定装置并根据需要使用工厂来构建数据(非常类似于FactoryGirl在 Rails 中),但不确定这在 Golang 中有多普遍。内置go test框架是最好的方法,还是有更好的选择?
查看完整描述

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)


查看完整回答
反对 回复 2022-01-17
?
www说

TA贡献1775条经验 获得超8个赞

关于 Rails 中类似 FactoryGirl 的测试夹具库,go 中有一些选择。

这两个图书馆得到的明星最多。

而且我还实现了与上述库相比类型安全、干燥且灵活的测试夹具库!


查看完整回答
反对 回复 2022-01-17
?
潇潇雨雨

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

    }

}


查看完整回答
反对 回复 2022-01-17
  • 3 回答
  • 0 关注
  • 126 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信