Ginkgo测试框架入门
为什么选择Ginkgo
目前基于 go 语言较为流行的测试框架:
Ginkgo (BDD)
在需求沟通上,若开发对需求的理解有偏差,就容易发生摩托变单车的事情。而BDD行为驱动测试就是为了解决这个问题,即先写功能描述。开发,测试,产品等都可以看懂,能低成本地纠正错误。
BDD可以得到我们对产品的理解提供反馈,更符合互联网团队目前对功能点的验收测试,也可结合TDD框架testify做更为细致的测试。
使用过rspec框架的会对Ginkgo的语法比较亲切,可以减少学习成本,Ginkgo的函数表达能力比较强, 功能也比较齐全
Name | Ginkgo | GoConvey | testify |
---|---|---|---|
Assertions | Gomega | ||
Style | spec | spec | assert |
Equal | ✓ | ✓ | ✓ |
IsSame | ✓ | ✓ | |
DeepEqual | ✓ | ✓ | |
True | ✓ | ✓ | ✓ |
False | ✓ | ✓ | ✓ |
Nil | ✓ | ✓ | ✓ |
Empty | ✓ | ✓ | ✓ |
Error | ✓ | ✓ | |
Implements | ✓ | ||
IsType | ✓ | ✓ | ✓ |
StringContains | ✓ | ✓ | ✓ |
StringMatches | ✓ | ||
Collection | ✓ | ✓ | |
Panics | ✓ | ✓ | ✓ |
HasLen | ✓ | ||
Matches | ✓ | ||
Satisfy | |||
Within |
框架简介
Ginkgo是golang的BDD类型的测试框架, ginkgo官方推进的匹配库是 gomega , 可以用它代替go内置的Testing的语法库,可以减少代码书写量,且语意更明确。
Quick Start
Step1. 安装
$ go get github.com/onsi/ginkgo/ginkgo $ go get github.com/onsi/gomega/...
Step2. 生成测试套件Suite
$ cd path/to/books $ ginkgo bootstrap
上述命令会自动生成,如下代码:
//path/to/books/books_suite_test.go package books_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "testing" ) func TestBooks(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Books Suite") }
需要注意的是这里package为 books_test , go中package的名字需要跟文件所在目录名一致packageName, 而packageName_test则是特例,在go中是允许的
Step3. 生成specs
$ ginkgo generate book
上述命令会自动生成,如下代码:
//path/to/books/book_test.go package books_test import ( . "/path/to/books" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Book", func() { })
Step4. 添加specs
//path/to/books/books_suite_test.go var _ = Describe("Book", func() { var ( book Book err error json string ) BeforeEach(func() { json = `{ "title":"Les Miserables", "author":"Victor Hugo", "pages":1488 }` }) JustBeforeEach(func() { book, err = NewBookFromJSON(json) }) Describe("loading from JSON", func() { Context("when the JSON parses succesfully", func() { It("should populate the fields correctly", func() { Expect(book.Title).To(Equal("Les Miserables")) Expect(book.Author).To(Equal("Victor Hugo")) Expect(book.Pages).To(Equal(1488)) }) It("should not error", func() { Expect(err).NotTo(HaveOccurred()) }) }) Context("when the JSON fails to parse", func() { BeforeEach(func() { json = `{ "title":"Les Miserables", "author":"Victor Hugo", "pages":1488oops }` }) It("should return the zero-value for the book", func() { Expect(book).To(BeZero()) }) It("should error", func() { Expect(err).To(HaveOccurred()) }) }) }) Describe("Extracting the author's last name", func() { It("should correctly identify and return the last name", func() { Expect(book.AuthorLastName()).To(Equal("Hugo")) }) }) })
method
Ginkgo提供了一系列拥可以嵌套的函数,来更丰富地描述测试,下面举几个比较常用的函数
Describe
描述一种行为或者一个方法
Context
丰富Describe所描述的行为或方法,增加条件语句,尽可能全地覆盖各种condition
it
申明用例, 期望这个用例得到的结果
Expect
这个是gomega提供的方法,用来断言结果
BeforeEach
会在每个小于等于beforeEach嵌套层的it函数之前运行,来设置公用的数据变量
JustBeforeEach
会在所有BeforeEach执行之后运行,在每个小于等于JustBeforeEach嵌套层的it函数之前运行, 可以有效避免重复创建
Mock
Ginkgo没有提供相关的mock方法,Ginkgo作者认为可以通过依赖注入和通过interface来实现, 他认为这比mock和stubs更清楚和富有表现力,话虽如此,但 Gomock 这个package,Ginkgo作者是比较推荐的,他实现mock相对来说比较简单
import ( "code.google.com/p/gomock/gomock" . github.com/onsi/ginkgo . github.com/onsi/gomega ) var _ = Describe("Consumer", func() { var ( mockCtrl *gomock.Controller mockThing *mockthing.MockThing consumer *Consumer ) BeforeEach(func() { mockCtrl = gomock.NewController(GinkgoT()) mockThing = mockthing.NewMockThing(mockCtrl) consumer = NewConsumer(mockThing) }) AfterEach(func() { mockCtrl.Finish() }) It("should consume things", func() { mockThing.EXPECT().OmNom() consumer.Consume() }) })
补充
此文档仅供快速入门,更多详细用法可以查询 官方文档