前言

Go语言本身集成了轻量级的测试框架,由go test命令和testing包组成。包含单元测试和压力测试,是保证我们编写健壮Golang程序的有效工具。

演示环境

$ uname -a
Darwin 18.6. Darwin Kernel Version 18.6.: Thu Apr :: PDT ; root:xnu-4903.261.~/RELEASE_X86_64 x86_64
$ go version
go version go1.12.4 darwin/amd64

示例

老规矩,我会用一个简单的示例演示go test的用法,让大家有一个直观的感受。

$ ls
my.go my_test.go
$ go test -v
=== RUN TestAbs
--- PASS: TestAbs (.00s)
PASS
ok mytest .006s

my.go文件内容:

package mytest

func Abs(a int) int {
if a < {
return -*a
}
return a
}

my_test.go文件的内容:

package mytest

import "testing"

func TestAbs(t *testing.T) {
result := Abs(-)
if result != {
t.Errorf("Abs(-1) = %d; want 1", result)
}
}

可以看出,测试文件是以_test.go结尾的文件,包含函数名TestXXX的文件签名func (t *testing.T)。测试框架会按函数定义的顺序依次执行Test开头的函数。如果测试函数调用错误函数,比如t.Error,t.Fail,那么测试就会认为是失败的。但是不会强制退出,测试程序还是会接着往下运行,除非调用t.Fatal,就会打印错误信息,并且强制退出。go test会自动编译运行_test.go结尾的文件,go build不会编译_test.go结尾的文件,所以不用担心test文件和正式文件定义为同一个包导致包大小增大。

详细用法

go test执行时会编译_test结尾的文件,执行文件中以Test,Benchmark,Example 开头的测试函数。建议_test.go文件和源文件声明为同一个包。单元测试函数TestXXX的参数是testing.T,BenchmarkXXX的参数是testing.B,函数内以b.N作为循环次数,其中N会动态变化。可以通过testing.T的Error,Errorf,Fail,Fatal,Fatalf 来说明测试不通过。

表格驱动测试

上述的示例单元测试用了-1这个测试用例来演示测试用法,但是在实际生产中我们编写一个测试函数肯定会有多种测试用例,各种边界条件,那这种情况应该怎么办呢?难道要每个测试用例拷贝一份上述的测试函数吗,显然是不合适的。这就介绍接下来的表格驱动测试(table driven test):

package mytest

import "testing"

func TestAbs(t *testing.T) {
var testcases = []struct {
in int
out int
}{
{-, },
{, },
{, },
{, },
{-, -},
}
for _, tc := range testcases {
result := Abs(tc.in)
if result != tc.out {
t.Fatalf("Abs(%d) = %d; want %d", tc.in, result, tc.out)
}
} }

表格的每一项是一个完整的测试用例,包含输入信息和期望的输出结果,有时候还包含测试用例名称等额外信息。这样我们就可以在表格里面编写各种测试用例场景,包括常规场景,边界场景,和一些异常场景。运行结果为:

$ go test -v
=== RUN TestAbs
--- FAIL: TestAbs (.00s)
my_test.go:: Abs(-) = ; want -
FAIL
exit status
FAIL mytest .005s

性能测试

性能测试函数以是Benchmark开头,格式为:

func Benchmark(b *testing.B)

go test 默认是不会运行_test.go文件中的Benchmark函数,需要通过-bench选项开启。演示代码:

package mytest

import "testing"

func BenchmarkAbs(b *testing.B) {
for i := ; i < b.N; i++ {
result := Abs(i)
if result != i {
b.Errorf("benchmark faild, abs(%d) result %d, except %d", i, result, i)
}
}
}

运行结果:

$ go test -bench=".*"
goos: darwin
goarch: amd64
pkg: mytest
BenchmarkAbs- 0.26 ns/op
PASS
ok mytest .553s

-bench后面跟的是正则表达式,我们可以指定需要匹配运行的benchmark函数,示例中的.*表示运行所有的benchmark函数。

上述结果显示总共运行了0.553s,一共运行了2000000000次,平均每次运行的时间是0.26纳秒。

总结

文章介绍了Go语言自带的go test测试框架的单元测试和性能测试方法。下篇将会讲解gomock模拟实际的生产接口。

参考

https://golang.org/pkg/testing/

https://github.com/golang/go/wiki/TableDrivenTests

https://golang.org/doc/code.html#Testing

go test 上篇的更多相关文章

  1. 看看C# 6.0中那些语法糖都干了些什么(上篇)

    今天没事,就下了个vs2015 preview,前段时间园子里面也在热炒这些新的语法糖,这里我们就来看看到底都会生成些什么样的IL? 一:自动初始化属性 确实这个比之前的版本简化了一下,不过你肯定很好 ...

  2. .Net开发笔记(十四) 基于“泵”的UDP通信(接上篇)

    上一篇中说到了“泵”在编程中的作用以及一些具体用处,但没有实际demo,可能不好理解,这篇文章我分享一个UDP通信的demo,大概实现了类似“飞鸽传书”在局域网中文本消息和文件传输的功能.功能不全也不 ...

  3. ASP.NET Core的配置(4):多样性的配置来源[上篇]

    较之传统通过App.config和Web.config这两个XML文件承载的配置系统,ASP.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命 ...

  4. ASP.NET Core的配置(3): 将配置绑定为对象[上篇]

    出于编程上的便利,我们通常不会直接利用ConfigurationBuilder创建的Configuration对象读取某个单一配置项的值,而是倾向于将一组相关的配置绑定为一个对象,我们将后者称为Opt ...

  5. 谈谈基于OAuth 2.0的第三方认证 [上篇]

    对于目前大部分Web应用来说,用户认证基本上都由应用自身来完成.具体来说,Web应用利用自身存储的用户凭证(基本上是用户名/密码)与用户提供的凭证进行比较进而确认其真实身份.但是这种由Web应用全权负 ...

  6. Sass-也许你想和CSS玩耍起来(上篇)

    我们努力,我们坚持,共勉! 众所周知,css其实不是一门编程语言,熟悉的人都知道css全称Cascading Style Sheets(层叠样式表)是一种用来表现HTML(标准通用标记语言的一个应用) ...

  7. Aoite 系列(04) - 强劲的 CommandModel 开发模式(上篇)

    Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.CommandModel 是一种开发模式,我把它成为"命令模型",这是一 ...

  8. 那些年我们写过的T-SQL(上篇)

    在当今这个多种不同数据库混用,各种不同语言不同框架融合的年代(一切为了降低成本并高效的提供服务),知识点多如牛毛.虽然大部分SQL脚本可以使用标准SQL来写,但在实际中,效率就是一切,因而每种不同厂商 ...

  9. 用MVVM做了一个保存网页的工具-上篇

    前言: 你是否有过收藏了别人博客或文章,当想用的时候却找不到?你是否有过收藏了别人博客或文章,却因为没有网络而打不开网页?OK,下面是我做的一个工具,有兴趣的同学们可以download 玩下,哈哈^. ...

  10. 【Remoting】.Net remoting方法实现简单的在线升级(上篇:更新文件)

    一.前言:       最近做一个简单的在线升级Demo,使用了微软较早的.Net Remoting技术来练手. 简单的思路就是在服务器配置一个Remoting对象,然后在客户端来执行Remoting ...

随机推荐

  1. MPchartAndroid-柱状图

    mChart = (LineChart) findViewById(R.id.chart1); mChart.setDescription("");    //设置图表描述信息 m ...

  2. my.ini配置详解

    Mysql my.ini 配置文件详解 #BEGIN CONFIG INFO #DESCR: 4GB RAM, 只使用InnoDB, ACID, 少量的连接, 队列负载大 #TYPE: SYSTEM ...

  3. Codeforces 586D Phillip and Trains(DP)

    题目链接 Phillip and Trains 考虑相对位移. 每一轮人向右移动一格,再在竖直方向上移动0~1格,列车再向左移动两格. 这个过程相当于每一轮人向右移动一格,再在竖直方向上移动0~1格, ...

  4. 正确地使用GIT FORK

    摘自github官方网站,稍后我将抽空翻译. Fork a repo https://help.github.com/articles/fork-a-repo/ Syncing a fork http ...

  5. python的依赖性安全性检查

    1.safety 安装: pip install safety 使用: 检查整个系统的依赖包安全性safety check检查某个项目的依赖性安全safety check -r requirement ...

  6. Linux USB驱动数据结构

    struct usb_ctrlrequest {    __u8 bRequestType;    __u8 bRequest;    __le16 wValue;    __le16 wIndex; ...

  7. 【Salvation】——人物角色动画实现

    写在前面:这个角色动画主要使用JavaScript编写脚本,在Unity3D游戏引擎的环境中实现. 一.显示角色并实现镜像效果 1.显示贴图: create→cube→修改名称为player,位置归0 ...

  8. linux 文件查找实用技巧

    1.tail catalina.out -n 100000 | grep -niR com.uujimu.utils.ArticleContentReplace.replacNumToA 查找内容,并 ...

  9. PHP之面向对象学习

    1.类 Class lio{ Public Protect Private Function __constructor(){} } 2.类的实例化 <? php class lio{ //定义 ...

  10. PropertiesTest

    import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public clas ...