单元测试是质量保证十分重要的一环,好的单元测试不仅能及时地发现问题,更能够方便地调试,提高生产效率。所以很多人认为写单元测试是需要额外的时间,会降低生产效率,是对单元测试最大的偏见和误解。

go 语言原生支持了单元测试,使用上非常简单,测试代码只需要放到以 _test.go 结尾的文件中即可。golang 的测试分为单元测试性能测试,单元测试的测试用例以 Test 开头,性能测试以 Benchmark 开头。

举个例子

实现排列组合函数对应的单元测试和性能测试。

实现排列组合函数

// combination.go
package hmath
func combination(m, n int) int {
   if n > m-n {
       n = m - n
   }
   c := 1
   for i := 0; i < n; i++ {
       c *= m - i
       c /= i + 1
   }
   return c
}

实现单元测试和性能测试

// combination_test.go
package hmath
import (
   "math/rand"
   "testing"
)
// 单元测试
// 测试全局函数,以TestFunction命名
// 测试类成员函数,以TestClass_Function命名
func TestCombination(t *testing.T) {
   // 这里定义一个临时的结构体来存储测试case的参数以及期望的返回值
   for _, unit := range []struct {
       m        int
       n        int
       expected int
   }{
       {1, 0, 1},
       {4, 1, 4},
       {4, 2, 6},
       {4, 3, 4},
       {4, 4, 1},
       {10, 1, 10},
       {10, 3, 120},
       {10, 7, 120},
   } {
       // 调用排列组合函数,与期望的结果比对,如果不一致输出错误
       if actually := combination(unit.m, unit.n); actually != unit.expected {
           t.Errorf("combination: [%v], actually: [%v]", unit, actually)
       }
   }
}
// 性能测试
func BenchmarkCombination(b *testing.B) {
   // b.N会根据函数的运行时间取一个合适的值
   for i := 0; i < b.N; i++ {
       combination(i+1, rand.Intn(i+1))
   }
}
// 并发性能测试
func BenchmarkCombinationParallel(b *testing.B) {
   // 测试一个对象或者函数在多线程的场景下面是否安全
   b.RunParallel(func(pb *testing.PB) {
       for pb.Next() {
           m := rand.Intn(100) + 1
           n := rand.Intn(m)
           combination(m, n)
       }
   })
}

运行测试

go test combination_test.go combination.go           # 单元测试
go test --cover combination_test.go combination.go   # 单元测试覆盖率
go test -bench=. combination_test.go combination.go  # 性能测试

setup 和 teardown

setup 和 teardown 是在每个 case 执行前后都需要执行的操作,golang 没有直接的实现,可以通过下面这个方法实现全局的 setup 和 teardown,具体每个 case 的 setup 和 teardown 需要自己实现。

func TestMain(m *testing.M) {
   // setup code...
   os.Exit(m.Run())
   // teardown code...
}

goconvey

这个第三方工具会自动帮我们跑测试,并且以非常友好的可视化界面帮我们展示测试的结果,包括测试失败的原因,测试覆盖率等等,内部还提供了很多友好的断言,能提高测试代码的可读性

使用方法

func TestMain(m *testing.M) {
   // setup code...
   os.Exit(m.Run())
   // teardown code...
}

goconvey

这个第三方工具会自动帮我们跑测试,并且以非常友好的可视化界面帮我们展示测试的结果,包括测试失败的原因,测试覆盖率等等,内部还提供了很多友好的断言,能提高测试代码的可读性

使用方法

go get github.com/smartystreets/goconvey

然后用终端在测试代码的目录下运行 goconvey 命令即可

测试例子

package package_name
import (
   "testing"
   . "github.com/smartystreets/goconvey/convey"
)
func TestIntegerStuff(t *testing.T) {
   Convey("Given some integer with a starting value", t, func() {
       x := 1
       Convey("When the integer is incremented", func() {
           x++
           Convey("The value should be greater by one", func() {
               So(x, ShouldEqual, 2)
           })
       })
   })
}

参考链接

go testing: http://docs.studygolang.com/pkg/testing/

goconvey: https://github.com/smartystreets/goconvey

goconvey 文档: https://github.com/smartystreets/goconvey/wiki/Documentation

goconvey 标准断言: https://github.com/smartystreets/goconvey/wiki/Assertions

thumb_up

转载|出处:http://t.cn/RnvsFRp

Golang技术交流群:426582602

golang 单元测试的更多相关文章

  1. ARTS-S golang单元测试

    golang单元测试 在$GOPATH的src目录下建目录demo_unittest 在目录demo_unittest下建文件calc.go,内容如下: package demo_unittest f ...

  2. Golang单元测试框架整理

    目录 一.单元测试是什么 二.单元测试的意义 三.Golang单元测试框架 3.1 Golang内置testing包 3.1.1 简单的测试 3.1.2 Benchmark 基准测试 3.1.3 运行 ...

  3. golang单元测试

    使用testing进行单元测试 golang的测试库testing 测试文件与被测试文件在同一个包中 测试文件名为被测试文件名(去后缀)_test.go 测试用例函数以Test开头,TestFunc1 ...

  4. golang 单元测试&&性能测试

    一:单元测试 1.为什么要做单元测试和性能测试 减少bug 快速定位bug 减少调试时间 提高代码质量 2.golang的单元测试 单元测试代码的go文件必须以_test.go结尾 单元测试的函数名必 ...

  5. golang 单元测试(一)

    单元测试函数类型 Test(功能测试) 函数规则: 函数名: TestXxxx , 以Test为前缀.Xxxx以大写字母开头 参数类型: *testing.T func TestXxxx(t *tes ...

  6. golang单元测试简述

      Golang中内置了对单元测试的支持,不需要像Java一样引入第三方Jar才能进行测试,下面将分别介绍Golang所支持的几种测试: 一.测试类型   Golang中单元测试有功能测试.基准测试. ...

  7. golang单元测试一(简单函数测试)

    0.1.索引 https://blog.waterflow.link/articles/1663688140724 1.简介 单元测试是测试代码.组件和模块的单元函数.单元测试的目的是清除代码中的错误 ...

  8. 【GoLang】GoLang 单元测试、性能测试使用方法

    单元测试代码: ackage test import ( // "fmt" "testing" ) func Test_FlowControl(t *testi ...

  9. Golang 单元测试和性能测试

    开发程序其中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早 ...

随机推荐

  1. 利用memcached实现分布式锁

    一  需求场景: (1) 需要限制用户创建提现订单的频率:目的一是防止前端bug引起的用户重复提交:二是防止并发攻击绕过提现策略(第一次提现和第二次提现门槛可能不同). (2) 需要限制秒杀下同一用户 ...

  2. selenium以及浏览器驱动下载安装

    1.下载selenium压缩包 http://pypi.python.org/pypi/selenium 下载后压缩在python文件下的lib>site-package文件夹下 2.进入sel ...

  3. 解决Bug步骤

    1.看报错.将bug定位到文件.类.方法. 2.打断点.将bug定位到具体代码行号. 3.分析断点输出结果. 4.结合报错和断点结果,修改代码. 总之:拆解问题.定位问题.分析问题.解决问题.

  4. PHP去重可用

    //国外 $arr6 = array_merge($arr2,$arr4); $arr8 = array(); $arr10 = array(); foreach($arr6 as $k6=> ...

  5. disconf实践(四)基于注解的分布式配置文件管理,自动reload

    上一篇讲解了基于xml的自动reload的分布式配置文件管理,这一篇讲解基于注解的自动reload的方式(基于disconf实践二). 1. 修改spring配置文件 <?xml version ...

  6. HDU 1058(打表)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1058 Humble Numbers Time Limit: 2000/1000 MS (Java/O ...

  7. oracle11g之管理oracle数据库笔记(理论基础知识)

                                                                  第三章 管理oracle数据库 1.启动数据库步骤;(创建启动实例--> ...

  8. HDU 2544最短路 (迪杰斯特拉算法)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2544 最短路 Time Limit: 5000/1000 MS (Java/Others)    Me ...

  9. Linux API fork 子进程 创建 & 无名管道通信

    #include<unistd.h> #include<stdio.h> int main() { ]; ]; pipe(filedes); printf("my p ...

  10. angular入门一之环境安装及项目创建

    angular入门一之环境安装及项目创建 1.安装node.js 下载,安装,在终端测试安装是否成功:node -v(查看nodejs版本) npm -v(查看npm版本) 下载地址:https:// ...