一旦工作,那就要努力的干,聪明的干,快速的干——用省下来的时间干自己喜欢干的事情。!

Go单元测试-GoConvey

go lampnick 1588℃ 0评论

特性

  • 集成go test
  • 可读的,带色彩的控制台输出
  • 全自动Web UI
  • 大量的回归测试套件
  • 测试代码生成

快速开始

  • 安装
$ cd <project path>
$ go get github.com/smartystreets/goconvey
$ $GOPATH/bin/goconvey
  • 打开浏览器
http://localhost:8080

如果存在测试代码,将会自动运行并展示在浏览器中

编写goconvey测试用例

Convey("Comparing two variables", t, func() {
	myVar := "Hello, world!"

	Convey(`"Asdf" should NOT equal "qwerty"`, func() {
		So("Asdf", ShouldNotEqual, "qwerty")
	})

	Convey("myVar should not be nil", func() {
		So(myVar, ShouldNotBeNil)
	})
})

如果有未完成的测试或场景,可以设置成nil或者skip

Convey("This isn't yet implemented", nil)

标准断言(Assertions):GoConvey自带了很多的标准断言,你可以用So()来使用。

  • General Equality
So(thing1, ShouldEqual, thing2)
So(thing1, ShouldNotEqual, thing2)
So(thing1, ShouldResemble, thing2)		// a deep equals for arrays, slices, maps, and structs
So(thing1, ShouldNotResemble, thing2)
So(thing1, ShouldPointTo, thing2)
So(thing1, ShouldNotPointTo, thing2)
So(thing1, ShouldBeNil)
So(thing1, ShouldNotBeNil)
So(thing1, ShouldBeTrue)
So(thing1, ShouldBeFalse)
So(thing1, ShouldBeZeroValue)
  • Numeric Quantity comparison
So(1, ShouldBeGreaterThan, 0)
So(1, ShouldBeGreaterThanOrEqualTo, 0)
So(1, ShouldBeLessThan, 2)
So(1, ShouldBeLessThanOrEqualTo, 2)
So(1.1, ShouldBeBetween, .8, 1.2)
So(1.1, ShouldNotBeBetween, 2, 3)
So(1.1, ShouldBeBetweenOrEqual, .9, 1.1)
So(1.1, ShouldNotBeBetweenOrEqual, 1000, 2000)
So(1.0, ShouldAlmostEqual, 0.99999999, .0001)   // tolerance is optional; default 0.0000000001
So(1.0, ShouldNotAlmostEqual, 0.9, .0001)
  • Collections
So([]int{2, 4, 6}, ShouldContain, 4)
So([]int{2, 4, 6}, ShouldNotContain, 5)
So(4, ShouldBeIn, ...[]int{2, 4, 6})
So(4, ShouldNotBeIn, ...[]int{1, 3, 5})
So([]int{}, ShouldBeEmpty)
So([]int{1}, ShouldNotBeEmpty)
So(map[string]string{"a": "b"}, ShouldContainKey, "a")
So(map[string]string{"a": "b"}, ShouldNotContainKey, "b")
So(map[string]string{"a": "b"}, ShouldNotBeEmpty)
So(map[string]string{}, ShouldBeEmpty)
So(map[string]string{"a": "b"}, ShouldHaveLength, 1) // supports map, slice, chan, and string
  • Strings
So("asdf", ShouldStartWith, "as")
So("asdf", ShouldNotStartWith, "df")
So("asdf", ShouldEndWith, "df")
So("asdf", ShouldNotEndWith, "df")
So("asdf", ShouldContainSubstring, "sd")		// optional 'expected occurences' arguments?
So("asdf", ShouldNotContainSubstring, "er")
So("adsf", ShouldBeBlank)
So("asdf", ShouldNotBeBlank)
  • panic
So(func(), ShouldPanic)
So(func(), ShouldNotPanic)
So(func(), ShouldPanicWith, "")		// or errors.New("something")
So(func(), ShouldNotPanicWith, "")	// or errors.New("something")
  • Type checking
So(1, ShouldHaveSameTypeAs, 0)
So(1, ShouldNotHaveSameTypeAs, "asdf")
  • time.Time (and time.Duration)
So(time.Now(), ShouldHappenBefore, time.Now())
So(time.Now(), ShouldHappenOnOrBefore, time.Now())
So(time.Now(), ShouldHappenAfter, time.Now())
So(time.Now(), ShouldHappenOnOrAfter, time.Now())
So(time.Now(), ShouldHappenBetween, time.Now(), time.Now())
So(time.Now(), ShouldHappenOnOrBetween, time.Now(), time.Now())
So(time.Now(), ShouldNotHappenOnOrBetween, time.Now(), time.Now())
So(time.Now(), ShouldHappenWithin, duration, time.Now())
So(time.Now(), ShouldNotHappenWithin, duration, time.Now())

自定义断言:有时一些特殊场景标准断言不能满足,需要使用自定义断言,只是实现一个函数具有以下签名(替换括号部分和字符串值):

func should<do-something>(actual interface{}, expected ...interface{}) string {
    if <some-important-condition-is-met(actual, expected)> {
        return ""   // empty string means the assertion passed
    }
    return "<some descriptive message detailing why the assertion failed...>"
}
如:
func shouldScareGophersMoreThan(actual interface{}, expected ...interface{}) string {
    if actual == "BOO!" && expected[0] == "boo" {
        return ""
    }
    return "Ha! You'll have to get a lot friendlier with the capslock if you want to scare a gopher!"
}
用例中调用So()
Convey("All caps always makes text more meaningful", func() {
    So("BOO!", shouldScareGophersMoreThan, "boo")
})

执行测试

go test -gcflags "all=-N -l" -v
go建议使用最新版本

用例执行顺序

  • 看下面例子
Convey A
    So 1
    Convey B
        So 2
    Convey C
        So 3
可能你一开始觉得会是A1B2C3这样顺序执行的,但是实际上是按照A1B2然后A1C3这样的顺序执行的。这种树形结构的测试行为消除了很多重复的设置代码。同时允许孤立的测试。
一个更加复杂的例子:
Convey A
    So 1
    Convey B
        So 2
        Convey Q
        	So 9
    Convey C
        So 3
执行顺序为:A1B2Q9A1C3
  • 陷阱
Convey("Setup", func() {
    foo := &Bar{}
    Convey("This creates a new variable foo in this scope", func() {
        foo := &Bar{}
    }
    Convey("This assigns a new value to the previous declared foo", func() {
        foo = &Bar{}
    }
}

每次调用Convey()都会创建一个新的scope,你应该使用Foo = &Bar{}为之前声明的变量赋值。使用foo := &Bar{}在当前scope中创建一个新变量。

Reset

  • 有时候需要在跑完一个用例后,清除converys中的一些预配置,这时应该使用Reset()来清除,如下例子:
Convey("Top-level", t, func() {

    // setup (run before each `Convey` at this scope):
    db.Open()
    db.Initialize()

    Convey("Test a query", func() {
        db.Query()
        // TODO: assertions here
    })

    Convey("Test inserts", func() {
        db.Insert()
        // TODO: assertions here
    })

    Reset(func() {
        // This reset is run after each `Convey` at the same scope.
        db.Close()
    })

})

Skip:有些场景需要忽略或都跳过整个scope或者一个So断言。在GoConvey中很容易实现

  • 跳过整个Convey
SkipConvey("Important stuff", func() {//这个方法不会执行
    Convey("More important stuff", func() {
        So("asdf", ShouldEqual, "asdf")
    })
})
  • 未完成的Convey
Convey("Some stuff", func() {

    // This will show up as 'skipped' in the report
    Convey("Should go boink", nil)

}
  • 跳过So断言:类似SkipConvey
Convey("1 Should Equal 2", func() {
    
    // This assertion will not be executed and will show up as 'skipped' in the report
    SkipSo(1, ShouldEqual, 2)

})

自动测试:GoConvey有两个运行自动测试的方式:在terminal和browser中

  • 在terminal中
下载https://gist.github.com/mdwhatcott/9107649
cd <folder_with_tests_or_packages>
auto-run.py -v
  • 在browser中:使用goconvey server

Web UI:一个强大的,简洁的在浏览器中展示go test结果的工具

  • 特点
    • 自定义监控目录
    • 当.go文件修改后自动更新Web UI
    • 测试代码生成
    • 浏览器通知
    • 失败的用例使用带颜色的输出
    • 嵌套显示GoConvey用例以方便阅读
    • 支持原生的go tests
    • 响应式页面设计
    • 高亮显示panics,build失败,失败用例

转载请注明:lampNick » Go单元测试-GoConvey

喜欢 (1)or分享 (0)
头像
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址