GO单元测试-GoConvey

原文:http://www.lampnick.com/php/732

特性

  • 集成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失败,失败用例
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值