Golang单元测试

Golang单元测试

参考几篇文章后,简单的进行了实践。感觉可以作为以后使用 golang 开发时,单元测试的固定套路。
首先介绍下这几个库

  • goconvey
    可以作为单元测试框架。提供web界面管理测试,不仅可以看到单元测试的成功失败,还可以看到测试的覆盖率。而且启动goconvey以后,可以在文件修改后,自动进行测试。
  • gostub 在测试过程中,根据需求动态修改全局变量的值(比如,使用测试专用的配置文件),根据需求指定某个函数的返回值。(专业术语叫打桩???)
  • gomock 专门用来测试接口的工具。可以根据接口定义来生成一个实现了接口的mock结构体。不过这个mock结构体上接口的每个函数返回值都需要根据测试来指定,这个mock结构体,可以在测试中使用。

goconvey

安装

go get github.com/smartystreets/goconvey

启动测试框架

cd $GOPATH/src/github.com/asdfsx/codility
goconvey

通过浏览器访问 http://127.0.0.1:8080/ 可以看到测试结果。更改上面的地址可以对不同目录下的代码进行测试。

goconvey 可以直接支持 golang 的 testing 模块。但是为了获得更好的输出,可以使用goconvey的api对测试进行包装

import(
  . "github.com/smartystreets/goconvey/convey"
  "testing"
)

func TestDB2(t *testing.T){
    ...
    Convey("CreateConnection", t, func(){
        dbConn, err = CreateConnection()
        So(err, ShouldEqual, nil)
    })
    ...
)

gostub

安装

go get github.com/prashantv/gostub

在测试的过程中,需要根据情况调整配置和一些全局变量,gostub 就是用来做这个的(打桩?)。

import (
	"testing"
	. "github.com/prashantv/gostub"
)

var (
	MYSQLUSER string
	MYSQLPASSWORD string
	MYSQLADDR string
	MYSQLPORT int
	DATABASENAME string
)

func Test1(t *testing.T){
	stubs := New()
	stubs.Stub(&MYSQLUSER, "root")
	stubs.Stub(&MYSQLPASSWORD, "root")
	stubs.Stub(&MYSQLADDR, "127.0.0.1")
	stubs.Stub(&MYSQLPORT, 3306)
	stubs.Stub(&DATABASENAME, "mysql")
	defer stubs.Reset()
	connstr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", MYSQLUSER, MYSQLPASSWORD, MYSQLADDR, MYSQLPORT, DATABASENAME)
	...
)

gomock

gomock 主要用来进行接口的测试。通过它提供的 mockgen 工具,会根据接口定义来生成接口测试用的文件。配合 gostub 对mock程序的行为进行打桩,然后就可以用来测试了。

安装

go get github.com/golang/mock/gomock
go install github.com/golang/mock/mockgen

使用 mockgen

mockgen -source db.go > mock_db.go 

mock_db.go 就是未来接口测试用到的mock类

import (
	"testing"
	. "github.com/smartystreets/goconvey/convey"
	. "github.com/prashantv/gostub"
	. "github.com/golang/mock/gomock"
)

func TestMock(t *testing.T){
	var newRedisRepo2 = newRedisRepo
	Convey("test obj demo", t, func() {
		Convey("create obj", func() {
			ctrl := NewController(t)
			defer ctrl.Finish()
			mockRepo := NewMockRepository(ctrl)
			mockRepo.EXPECT().Retrieve(Any()).Return(nil, nil)
			mockRepo.EXPECT().Create(Any(), Any()).Return(nil)
			mockRepo.EXPECT().Retrieve(Any()).Return(nil, nil)
			stubs := StubFunc(&newRedisRepo2, mockRepo)
			defer stubs.Reset()
			So(repo.Create("", nil), ShouldBeNil)
		})
	})
}


总结

灵活使用以上3个工具应该能满足绝大多数的测试场景。接下来就是多用多看相关文档了。

参考文章

GoConvey框架使用指南
GoStub框架使用指南
GoMock框架使用指南

 
comments powered by Disqus