Golang测试包

golang自带了测试包(testing),直接可以进行单元测试、性能分析、输出结果验证等。简单看着官方文档试了试,总结一下:

目录结构和命令

使用golang的测试包,需要遵循简单的目录结构

测试代码放在待测试代码的目录下(一个包内),以_test.go结尾,例如如下目录结构,MyTest目录下有待测试的代码文件MyTest.go和测试代码MyTest_test.go

.
|-- bin
| `-- main
|-- pkg
| `-- darwin_amd64
| `-- MyTest.a
`-- src
|-- MyTest
| |-- MyTest.go
| `-- MyTest_test.go
`-- main
`-- main.go

直接在MyTest目录下执行go test命令即可,go test包含很多选项,可以参考Golang手册相关部分

基本的测试函数

待测试的MyTest.go源码如下:

package MyTest

import (
"fmt"
) type MyStruct struct {
name string
} func GetFieldValue(x *MyStruct) string {
value := x.name
return value
} func SetFieldValue(x *MyStruct, value string) {
fmt.Println("SetFieldValue()")
x.name = value
}

对于MyTest_test.go,首先自然是要导入golang的测试包

package MyTest
import testing

基本的测试函数以Test开头,后面接的字符串,第一个字符必须是数字或者大写,例如:

func TestMytest(t *testing.T) {
var st MyStruct
SetFieldValue(&st, "hello")
val := GetFieldValue(&st) if val != "hello" {
t.Error("Set Field")
}
}

T是testing包里定义的一个结构体,其包含了名为common的接口,提供了很多格式化输出的功能,golang提供了自动检查与调用测试函数的机制,测试函数的执行逻辑则需要编写者自行完成。

执行go test 结果为:

Call SetFieldValue()
PASS
ok /go/src/MyTest .004s

如果写成Testmytest,运行时会直接忽略掉该函数。得到的结果仍然为Pass,但是不会打印“Call SetFieldValue()”,也就是说测试函数实际没有执行。
修改一下判断条件:

func TestMytest(t *testing.T) {
var st MyStruct
SetFieldValue(&st, "hello")
val := GetFieldValue(&st) if val != "world" {
t.Error("Set Field")
}
}

这个测试用例不会通过, 而Error函数的入参就是测试不通过时打印的信息:

SetFieldValue()
--- FAIL: TestMytest (.00s)
MyTest_test.go:: Set Field
FAIL
exit status
FAIL _/Users/ronghuihe/Documents/code/golang/my/go/src/MyTest .004s

这并不会中断测试程序,这个函数后面的部分仍然会执行,其他的测试函数也会执行。

性能分析函数

testing包还自带了性能分析功能,可评估代码执行性能。性能分析函数也可以放到前面的xxx_test.go文件内,命名以Benchmark开头,如:

func BenchmarkGetFieldValue(b *testing.B) {
var st MyStruct
SetFieldValue(&st, "hello") for i := ; i < b.N; i++ {
GetFieldValue(&st)
}
}

其中b.N的值在执行过程中会自动调整,使得循环可以执行足够多次,以便得到较为准确的单次结果:
性能分析加-bench参数执行,即go test -bench . (不能漏了最后这个点,它表示执行所有的性能测试函数)

BenchmarkGetFieldValue    SetFieldValue()
SetFieldValue()
SetFieldValue()
SetFieldValue()
SetFieldValue()
SetFieldValue()
0.55 ns/op

每次循环大约需要0.55ns。这里SetFieldValue()打印了多次,是因为BenchmarkGetFieldValue被调用了多次。
分析testing包的源码benchmark.go里的launch函数和runN函数,可以看到golang会自行调节性能分析函数的调用次数。每次执行runN都会执行一次性能测试函数,而后根据运行时间,会确定后续的内部循环执行次数b.N,直到总的运行时间达到go test -benchtime指定的时间(如果没指定默认为1s)

注意统计时间时,执行的是使用者编写的性能分析函数,如上例中的BenchmarkGetFieldValue,而最后输出的结果,表达的是for循环里函数的性能,因此for循环之前的代码执行时间很长的话,可能导致统计误差比较大,如果需要剔除for之前代码的影响,可以在for循环之前调用ResetTimer()接口重置本次统计的时间值:

func BenchmarkGetFieldValue(b *testing.B) {
var st MyStruct
SetFieldValue(&st, "hello") b.ResetTimer()
for i := ; i < b.N; i++ {
GetFieldValue(&st)
}
}

Golang测试包的更多相关文章

  1. Golang测试技术

    本篇文章内容来源于Golang核心开发组成员Andrew Gerrand在Google I/O 2014的一次主题分享“Testing Techniques”,即介绍使用Golang开发 时会使用到的 ...

  2. Golang Vendor 包管理工具 glide 使用教程

    Glide 是 Golang 的 Vendor 包管理器,方便你管理 vendor 和 verdor 包.类似 Java 的 Maven,PHP 的 Composer. Github:https:// ...

  3. golang测试

    简述 Go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试. go test [-c] [-i] [build flags] [packages] [f ...

  4. Golang ---testing包

    golang自带了testing测试包,使用该包可以进行自动化的单元测试,输出结果验证,并且可以测试性能. 建议安装gotests插件自动生成测试代码: go get -u -v github.com ...

  5. 如何利用Pre.im分发iOS测试包

    大众创新万众创业,在移动互联网的风口,移动APP开发与测试发展方兴未艾,受到了越来越多的重视.相较 iOS,Android 的开发环境更加开放.Android 开发者要测试应用时,只需发个 APK 安 ...

  6. Golang fmt包使用小技巧

    h1 { margin-top: 0.6cm; margin-bottom: 0.58cm; direction: ltr; color: #000000; line-height: 200%; te ...

  7. Xcode9 打包ipa(导出ipa测试包)时总是意外退出

    今天用xcode9,打包ipa总是意外退出. 正处在测试阶段,所以打的也是测试包 ,路径是:Product -> Archive -> Export -> Save for Ad H ...

  8. Golang Vendor 包机制 及 注意事项

    现在的 Go 版本是 1.8,早在 1.5 时期,就有了 Vendor 包机制,详情可查看博文:“理解 Go 1.5 vendor”. 遇到的问题 个人在使用 Glide 管理 Vendor 包时(附 ...

  9. golang reflect包使用解析

    golang reflect包使用解析 参考 Go反射编码 2个重要的类型 Type Value 其中Type是interface类型,Value是struct类型,意识到这一点很重要 Type和Va ...

随机推荐

  1. 三:SQL server基础

    /一:创建数据库/ use master if exists (select * from sysdatabases where name='数据库名称') drop database 数据库名称 - ...

  2. ubuntu 配置dns访问外网

    我新建了一个虚拟机后采用的net模式 一 先配置虚拟机ip使其能在局域网内通信 1.vmware 编辑->虚拟网络编辑器 可以看到网关.掩码等信息 可以看到我们配置的ip应该在192.168.1 ...

  3. delphi之读写文件的三种方式

    一.Tstrings.Tstringlist procedure TForm1.Button2Click(Sender: TObject); var strlist: TStringList; pat ...

  4. CNN中卷积过程中padding的使用

    1.podding='SAME'时,全0填充.     2.padding=“VALID”,不使用全0填充      

  5. [CTSC2008]祭祀(构造方案)

    前面的话 这道题显然就是最长反链 根据 \(Dilworth\) 定理:最小链覆盖数 = 最长反链长度 然后传递闭包跑匹配即可 \(luogu\)交了一下,\(WA\) 了 \(QAQ\) 本来各种 ...

  6. Nodejs + express post get 参数获取小结

    req.params.xxxxx 从path中的变量 req.query.xxxxx 从get中的?xxxx=中 req.body.xxxxx 从post中的变量 Post下别忘了: app.use( ...

  7. win10命令控制符

    IP:ipconfigIP地址侦测器:Nslookup显卡:dxdiag控制面板:control电话拨号:dialer木马捆绑工具,系统自带:iexpress本地用户和组:lusrmgr.msc鼠标属 ...

  8. Box(视图组件)如何在多个页面不同视觉规范下的复用

    本文来自 网易云社区 . 问题描述 Android App中的页面元素,都是由一个个Box(可以理解成一个个自定义View组件和Widget同级)组成,这些Box可以在不同的页面.不同的模块达到复用的 ...

  9. pytorch 文本输入处理

    https://blog.csdn.net/nlpuser/article/details/88067167 https://blog.csdn.net/u012436149/article/deta ...

  10. *.vue文件的template标签内使用form标签

    由于form表单有重复提交的问题,所以在vue文件内直接使用form标签时需要注意这个问题,否则会导致页面重复刷新跳转不成功的问题 解决方案: <form @submit.prevent> ...