为什么要使用goconvey测试程序

goconvey 集成go test,go test 无缝接入。管理运行测试用例,而且提供了丰富的函数断言、非常友好的WEB界面,直观的查看测试结果。

如果没有goconvey的话,编写一个测试结果,首先运行被测试函数,然后判断被测试函数的运行结果,各种if判断,各种输出提示信息,而且回归测试也比较麻烦。但是如果使用了goconvey这些都就变得无比的简单。

还是看些使用代码比较简单明了。

怎么使用goconvey测试程序

第一步当然是安装goconvey

  1. go get github.com/smartystreets/goconvey

看下被测试的代码

  1. package main
  2. import "fmt"
  3. type Student struct {
  4. Num int
  5. Name string
  6. Chinaese int
  7. English int
  8. Math int
  9. }
  10. func NewStudent(num int, name string) (*Student,error) {
  11. if num < 1 || len(name) < 1 {
  12. return nil,fmt.Errorf("num name empty")
  13. }
  14. stu := new(Student)
  15. stu.Num = num
  16. stu.Name = name
  17. return stu,nil
  18. }
  19. func (this *Student) GetAve() (int,error) {
  20. score := this.Chinaese + this.English + this.Math
  21. if score == 0 {
  22. return 0,fmt.Errorf("score is 0")
  23. }
  24. return score/3,nil
  25. }

主要看下goconvey的测试代码

  1. package main
  2. import (
  3. "testing"
  4. . "github.com/smartystreets/goconvey/convey"
  5. )
  6. func TestNew(t *testing.T) {
  7. Convey("start test new", t, func() {
  8. stu,err := NewStudent(0,"")
  9. Convey("have error", func() {
  10. So(err, ShouldBeError)
  11. })
  12. Convey("stu is nil", func() {
  13. So(stu, ShouldBeNil)
  14. })
  15. })
  16. }
  17. func TestScore(t *testing.T) {
  18. stu,_ := NewStudent(1,"test")
  19. Convey("if error", t, func() {
  20. _,err := stu.GetAve()
  21. Convey("have error", func() {
  22. So(err, ShouldBeError)
  23. })
  24. })
  25. Convey("normal", t, func() {
  26. stu.Math = 60
  27. stu.Chinaese = 70
  28. stu.English = 80
  29. score,err := stu.GetAve()
  30. Convey("have error", func() {
  31. So(err, ShouldBeError)
  32. })
  33. Convey("score > 60", func() {
  34. So(score, ShouldBeGreaterThan, 60)
  35. })
  36. })
  37. }

进入到test代码目录,执行 go test

  1. === RUN TestNew
  2. start test new
  3. have error
  4. stu is nil
  5. 2 total assertions
  6. --- PASS: TestNew (0.00s)
  7. === RUN TestScore
  8. if error
  9. have error
  10. 3 total assertions
  11. normal
  12. have error
  13. score > 60
  14. Failures:
  15. * /data/www/go/src/test/student_test.go
  16. Line 35:

其实命令行显示的是有颜色标识的。期望出现的结果都会打上对勾,如果期望出现而没有出现的都会打上叉。

还有更好玩的WEB界面。进入的test代码的目录,然后执行 goconvey 会打开一个WEB界面,更加友好的标识出了测试的结果,测试了多少次,有几个通过,几个失败,一目了然。



其实使用特别简单

引入类库,启动Convey函数,剩下的就是调用So各种断言各种比较

  1. import (
  2. "testing"
  3. . "github.com/smartystreets/goconvey/convey"
  4. )
  5. Convey("desc", t, func() {
  6. So(var, function
  7. })

基本平常开发中的比较函数基本都有,看下比较的函数列表,看着貌似都涵盖了。

  1. Convey("Equality assertions should be accessible", t, func() {
  2. thing1a := thing{a: "asdf"}
  3. thing1b := thing{a: "asdf"}
  4. thing2 := thing{a: "qwer"}
  5. So(1, ShouldEqual, 1)
  6. So(1, ShouldNotEqual, 2)
  7. So(1, ShouldAlmostEqual, 1.000000000000001)
  8. So(1, ShouldNotAlmostEqual, 2, 0.5)
  9. So(thing1a, ShouldResemble, thing1b)
  10. So(thing1a, ShouldNotResemble, thing2)
  11. So(&thing1a, ShouldPointTo, &thing1a)
  12. So(&thing1a, ShouldNotPointTo, &thing1b)
  13. So(nil, ShouldBeNil)
  14. So(1, ShouldNotBeNil)
  15. So(true, ShouldBeTrue)
  16. So(false, ShouldBeFalse)
  17. So(0, ShouldBeZeroValue)
  18. So(1, ShouldNotBeZeroValue)
  19. })
  20. Convey("Numeric comparison assertions should be accessible", t, func() {
  21. So(1, ShouldBeGreaterThan, 0)
  22. So(1, ShouldBeGreaterThanOrEqualTo, 1)
  23. So(1, ShouldBeLessThan, 2)
  24. So(1, ShouldBeLessThanOrEqualTo, 1)
  25. So(1, ShouldBeBetween, 0, 2)
  26. So(1, ShouldNotBeBetween, 2, 4)
  27. So(1, ShouldBeBetweenOrEqual, 1, 2)
  28. So(1, ShouldNotBeBetweenOrEqual, 2, 4)
  29. })
  30. Convey("Container assertions should be accessible", t, func() {
  31. So([]int{1, 2, 3}, ShouldContain, 2)
  32. So([]int{1, 2, 3}, ShouldNotContain, 4)
  33. So(map[int]int{1: 1, 2: 2, 3: 3}, ShouldContainKey, 2)
  34. So(map[int]int{1: 1, 2: 2, 3: 3}, ShouldNotContainKey, 4)
  35. So(1, ShouldBeIn, []int{1, 2, 3})
  36. So(4, ShouldNotBeIn, []int{1, 2, 3})
  37. So([]int{}, ShouldBeEmpty)
  38. So([]int{1}, ShouldNotBeEmpty)
  39. So([]int{1, 2}, ShouldHaveLength, 2)
  40. })
  41. Convey("String assertions should be accessible", t, func() {
  42. So("asdf", ShouldStartWith, "a")
  43. So("asdf", ShouldNotStartWith, "z")
  44. So("asdf", ShouldEndWith, "df")
  45. So("asdf", ShouldNotEndWith, "as")
  46. So("", ShouldBeBlank)
  47. So("asdf", ShouldNotBeBlank)
  48. So("asdf", ShouldContainSubstring, "sd")
  49. So("asdf", ShouldNotContainSubstring, "af")
  50. })
  51. Convey("Panic recovery assertions should be accessible", t, func() {
  52. So(panics, ShouldPanic)
  53. So(func() {}, ShouldNotPanic)
  54. So(panics, ShouldPanicWith, "Goofy Gophers!")
  55. So(panics, ShouldNotPanicWith, "Guileless Gophers!")
  56. })
  57. Convey("Type-checking assertions should be accessible", t, func() {
  58. // NOTE: Values or pointers may be checked. If a value is passed,
  59. // it will be cast as a pointer to the value to avoid cases where
  60. // the struct being tested takes pointer receivers. Go allows values
  61. // or pointers to be passed as receivers on methods with a value
  62. // receiver, but only pointers on methods with pointer receivers.
  63. // See:
  64. // http://golang.org/doc/effective_go.html#pointers_vs_values
  65. // http://golang.org/doc/effective_go.html#blank_implements
  66. // http://blog.golang.org/laws-of-reflection
  67. So(1, ShouldHaveSameTypeAs, 0)
  68. So(1, ShouldNotHaveSameTypeAs, "1")
  69. So(bytes.NewBufferString(""), ShouldImplement, (*io.Reader)(nil))
  70. So("string", ShouldNotImplement, (*io.Reader)(nil))
  71. })
  72. Convey("Time assertions should be accessible", t, func() {
  73. january1, _ := time.Parse(timeLayout, "2013-01-01 00:00")
  74. january2, _ := time.Parse(timeLayout, "2013-01-02 00:00")
  75. january3, _ := time.Parse(timeLayout, "2013-01-03 00:00")
  76. january4, _ := time.Parse(timeLayout, "2013-01-04 00:00")
  77. january5, _ := time.Parse(timeLayout, "2013-01-05 00:00")
  78. oneDay, _ := time.ParseDuration("24h0m0s")
  79. So(january1, ShouldHappenBefore, january4)
  80. So(january1, ShouldHappenOnOrBefore, january1)
  81. So(january2, ShouldHappenAfter, january1)
  82. So(january2, ShouldHappenOnOrAfter, january2)
  83. So(january3, ShouldHappenBetween, january2, january5)
  84. So(january3, ShouldHappenOnOrBetween, january3, january5)
  85. So(january1, ShouldNotHappenOnOrBetween, january2, january5)
  86. So(january2, ShouldHappenWithin, oneDay, january3)
  87. So(january5, ShouldNotHappenWithin, oneDay, january1)
  88. So([]time.Time{january1, january2}, ShouldBeChronological)
  89. })

特别实用的一个测试类库,养成写完代码使用goconvey做测试的好习惯,也顺便覆盖下使用方法和案例,定能让开发事半功倍,减少Bug率。

golang开发:类库篇(五)go测试工具goconvey的使用的更多相关文章

  1. golang开发:类库篇(三)命令行工具cli的使用

    为什么要使用命令行 觉得这个问题不应该列出来,又觉得如果初次进行WEB开发的话,可能会觉得所有的东西都可以使用API去做,会觉得命令行没有必要. 其实,一个生产的项目命令行是绕不过去的.比如运营需要导 ...

  2. golang开发:环境篇(五)实时加载工具gin的使用

    gin 工具是golang开发中非常有用且有效的工具,有效的提高了开发调试go程序的效率. 为什么要使用gin 我们知道golang是编译型语言,这就表示go程序的每次改动,如果需要查看改动结果都必须 ...

  3. golang开发:类库篇(一) Zap高性能日志类库的使用

    为什么要用zap来写日志 原来是写PHP的,一直用的error_log,第一次写Go项目的时候,还真不知道该怎么写日志,后来就按照PHP的写法自己不成规范的捣鼓写.去了新公司之后,发现用的是zap.后 ...

  4. golang开发:类库篇(二) Redis连接池的使用

    为什么要使用连接池 一个数据库服务器只拥有有限的连接资源,一旦所有的连接资源都在使用,那么其它需要连接的资源就只能等待释放连接资源.所以,在连接资源有限的情况下,提高单位时间的连接的使用效率,缩短连接 ...

  5. golang开发:类库篇(四)配置文件解析器goconfig的使用

    为什么要使用goconfig解析配置文件 目前各语言框架对配置文件书写基本都差不多,基本都是首先配置一些基础变量,基本变量里面有环境的配置,然后通过环境变量去获取该环境下的变量.例如,生产环境跟测试环 ...

  6. modern.IE – Web 开发必备的 IE 浏览器测试工具

    modern.IE 是微软推出的一个开发人员中心,提供免费的工具和资源,旨在使您能够花更少的时间来测试各种版本的 Internet Explorer,并留出更多时间在现代 Web 上构建重要的内容.m ...

  7. Golang之框架篇-Windows环境bee工具运行beego

    bee工具简介及好处     bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 你可以很容易的进行 beego 项目的创建.热编译.开发.测试.和部署. 强烈推荐新手或J ...

  8. golang开发:环境篇(六) Go运行监控Supervisord的使用

    为什么要使用Supervisord 17年第一次写Go项目的时候,用Go开发项目倒没没费多大劲,很快就开发完成了.到了在测试环境部署的时候,由于不知道有 Supervisord 这个软件,着实花了些功 ...

  9. golang开发:环境篇(四)包管理器 glide的使用

    glide 是golang项目开发中是特别重要的软件,没有它,golang的项目可能都无法发布. 为什么要使用glide 平时我们开发Go项目的时候,使用第三方的包的时候都直接使用go get 去获取 ...

随机推荐

  1. GitHub项目:jkrasnay/sqlbuilder的使用

    http://www.jianshu.com/p/7f099b8cf5f0 技术选型: 在报表查询时,通常需要做可以动态添加的条件 在老项目中使用的是一种Tcondition的对象分装sql impo ...

  2. MYSQL 入门配置

    1.下载 MYSQL官网 2.目录结构图基本如下 3.运行CMD(管理员权限),进入MYSQL目录下面的bin目录 4.执行 mysqld install 5.执行 net start mysql 6 ...

  3. Swift项目引入第三方库的方法

    以下,将创建一个Swift项目,然后引入3个库: Snappy 简化autolayout代码的库 Alamofire HTTP网络库,AFNetworking作者写的 SDWebImage 图片加载, ...

  4. Selenium+java - Page Object设计模式

    前言 Page Object(页面对象)模式,是Selenium实战中最为流行,并且被自动化测试同学所熟悉和推崇的一种设计模式之一.在设计测试时,把页面元素定位和元素操作方法按照页面抽象出来,分离成一 ...

  5. powerdesigner16.6版本resource的重复使用

    今天早上遇到想要重复使用resource ,但是发现powerdesigner16.6版本跟16.5版本有关重复使用name的设置已经不一样了,网上找了好久没找到,软件上找了好久也没找到相应的设置. ...

  6. laravel为模型中所有查询统一添加WHERE条件

    在使用laravel开发web系统的过程,需要在model处为该模型统一添加一个条件或者多个条件,研究了一个laravel的模型类,发现model中有个方法是构建查询的,方法如下: /** * Reg ...

  7. U盘制作启动盘后空间容量变小解决方法

    WinAll的快速恢复方式: 0.windows键+R(调出运行窗口)输入:diskpart回车(调出磁盘管理器) 1.输入:list disk回车(从大小容量确定目标U盘的盘符X) 2.输入:sel ...

  8. bootstrap-datetimepicker时间插件使用

    html头部引入相关的js和css <link rel="stylesheet" type="text/css" href="css/boots ...

  9. 使用注解的Hibernate one-to-many映射

    One to many映射关系指的是两个实体间一个实体可以和多个实体有关联关系,但是多的这一端只能和一的这一端的一个实例有关系.它是一个1 到 n的关系.例如在任何的公司员工可以注册多个银行账户,一个 ...

  10. jQuery Validate 可选项