golang 单元测试(一)
单元测试函数类型
Test(功能测试)
函数规则:
- 函数名: TestXxxx , 以Test为前缀。Xxxx以大写字母开头
- 参数类型: *testing.T
func TestXxxx(t *testing.T){...}
编写一个简单的例子,假设有下面一个待测函数:
func add(a, b int) int {
return a + b
}
测试代码如下:
import "testing"
func TestAdd(t *testing.T) {
cases := []struct {
first int
second int
excepted int
}{
{1, 2, 3},
{1, 2, 4},
}
for _, c := range cases {
result := add(c.first, c.second)
if result != c.excepted {
t.Fatalf("add function failed, first: %d, second:%d, execpted:%d, result:%d", c.first, c.second, c.excepted, result)
}
}
}
执行 go go test -v
结果如下:
=== RUN TestAdd
--- FAIL: TestAdd (0.00s)
example_test.go:30: add function failed, first: 1, second:2, execpted:4, result:3
FAIL
exit status 1
FAIL gotest/gotest 0.006s
第二个测试用例出错,未能通过单元测试,需要检查测试数据或者被测试函数是否符合我们的预期。
从上述过程可以看出, TestXxxx 可以理解为功能性测试,其目的在于测试函数的功能性是否正确, 应当编写尽可能多的测试用例来验证被测函数的正确性。
Benchmark(基准测试)
函数规则:
- 函数名: BenchmarkXxxx, 以Benchmark为前缀。Xxxx以大写字母开头
- 参数类型: *testing.B
func BenchmarkXxx(b *testing.B){...}
性能测试函数如下:
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
add(1, 2)
}
}
执行 go test -bench=. -run=^$
,结果如下:
goos: darwin
goarch: amd64
pkg: gotest/gotest
BenchmarkAdd-8 2000000000 0.32 ns/op
PASS
ok gotest/gotest 0.667s
测试结果说明:
- -8 表示 8个逻辑cpu个数(下文会解释)
- 2000000000 表示执行了 2000000000 次
- 0.32 ns/op 每次操作耗时
- 0.667s 是总时长
性能测试函数计时器:
当性能测试函数中有一些额外的初始化操作时,可以通过启停计时器来屏蔽这些操作对最终性能测试的影响。简单例子如下:
func BenchmarkAdd(b *testing.B) {
time.Sleep(10 * time.Second)
for i := 0; i < b.N; i++ {
add(1, 2)
}
}
执行命令go test -bench=.
,结果如下:
goos: darwin
goarch: amd64
pkg: gotest/gotest
BenchmarkAdd-8 1 10004479538 ns/op
PASS
ok gotest/gotest 10.011s
单个测试函数耗时为 10004479538 ns,同时我们也可以看到,这个函数执行一次就已经达到了最大上限时间。
加上时间计数器:
func BenchmarkAdd(b *testing.B) {
b.StopTimer()
time.Sleep(10 * time.Second)
b.StartTimer()
for i := 0; i < b.N; i++ {
add(1, 2)
}
}
测试结果如下:
goos: darwin
goarch: amd64
pkg: gotest/gotest
BenchmarkAdd-8 2000000000 0.34 ns/op
PASS
ok gotest/gotest 60.751s
单次执行耗时为: 0.34 ns 了。
Tips:
对于 b.N 参数而言, test 命令先会尝试设置为1,之后执行函数。如果测试函数没有达到执行上限的话, test 函数会增大,之后再次执行测试函数,如此往复,直到执行时间大于或者等于上限时间为止。 上限时间可以使用 -benchtime
设定
Example(示例测试)
函数规则:
- 函数名: ExampleXxx
- 输出内容至标准输出,参数列表没有限制
示例测试函数如下:
func Println(content string) {
fmt.Println("The output of\nthis example.")
}
func ExamplePrintln() {
Println("The output of\nthis example.")
// Output: The output of
// this example.
}
go test 命令会检测实际输出与注释中的期望输出是否一致, 一致则测试通过,不一致则测试失败。
go test 常用参数
- -cpu: 设置测试最大 cpu 逻辑数(也就是 GPM 中 P, 最大并行执行的 gorouting 数量, 默认等于 cpu 核数)
- -count: 设置执行测试函数的次数, 默认为 1
- -run: 执行功能测试函数, 支持正则匹配, 可以选择测试函数或者测试文件来仅测试单个函数或者单个文件
- -bench: 执行基准测试函数, 支持正在匹配
- -benchtime: 基准测试最大探索时间上限
- -parallel: 设置同一个被测试代码包中的功能测试函数的最大并发执行数
- -v: 是展示测试过程信息
更多的参数可以参考下文的官方文档
参考
golang 单元测试(一)的更多相关文章
- ARTS-S golang单元测试
golang单元测试 在$GOPATH的src目录下建目录demo_unittest 在目录demo_unittest下建文件calc.go,内容如下: package demo_unittest f ...
- Golang单元测试框架整理
目录 一.单元测试是什么 二.单元测试的意义 三.Golang单元测试框架 3.1 Golang内置testing包 3.1.1 简单的测试 3.1.2 Benchmark 基准测试 3.1.3 运行 ...
- golang单元测试
使用testing进行单元测试 golang的测试库testing 测试文件与被测试文件在同一个包中 测试文件名为被测试文件名(去后缀)_test.go 测试用例函数以Test开头,TestFunc1 ...
- golang 单元测试
单元测试是质量保证十分重要的一环,好的单元测试不仅能及时地发现问题,更能够方便地调试,提高生产效率.所以很多人认为写单元测试是需要额外的时间,会降低生产效率,是对单元测试最大的偏见和误解. go 语言 ...
- golang 单元测试&&性能测试
一:单元测试 1.为什么要做单元测试和性能测试 减少bug 快速定位bug 减少调试时间 提高代码质量 2.golang的单元测试 单元测试代码的go文件必须以_test.go结尾 单元测试的函数名必 ...
- golang单元测试简述
Golang中内置了对单元测试的支持,不需要像Java一样引入第三方Jar才能进行测试,下面将分别介绍Golang所支持的几种测试: 一.测试类型 Golang中单元测试有功能测试.基准测试. ...
- golang单元测试一(简单函数测试)
0.1.索引 https://blog.waterflow.link/articles/1663688140724 1.简介 单元测试是测试代码.组件和模块的单元函数.单元测试的目的是清除代码中的错误 ...
- 【GoLang】GoLang 单元测试、性能测试使用方法
单元测试代码: ackage test import ( // "fmt" "testing" ) func Test_FlowControl(t *testi ...
- Golang 单元测试和性能测试
开发程序其中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早 ...
随机推荐
- pip安装报错Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-e_k8hq6a/pynacl/
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-e_k8hq6a/pyn ...
- sass - for循环写法
如要设置多个li的动画延迟时间时 注:这里选择器要加#{}才行 不然就会编译成: 6.7. 插值语句 #{} (Interpolation: #{}) 通过 #{} 插值语句可以在选择器或属性名中使用 ...
- android -------- java.net.UnknownServiceException
最近升级了Android的API版本时 ,导致我的网络请求失败了, 出现了这个错误 java.net.UnknownServiceException, 这个错误,我在网上查到这个主要是由于,我们的Ok ...
- Spring Boot TImer Schedule Quartz
Spring Boot 2.X(十二):定时任务-云栖社区-阿里云https://yq.aliyun.com/articles/723876?spm=a2c4e.11155472.0.0.2f8b3a ...
- Mac 安装 7zip
可以使用 Homebrew 安装, p7zip 是 7-zip for Unix/Linux 的命令行版本,由独立开发人员开发 为了获取到最新版本的 p7zip,你需要更新你的 brew $ brew ...
- IDEA优化配置,提高启动和运行速度
IDEA优化配置,提高启动和运行速度 参考链接:https://blog.csdn.net/riju4713/article/details/83217013,http://www.pc0359. ...
- Swift编码总结1
1. fileprivate (set) var hasSetDiscount = false中fileprivate (set)表示什么意思: //设置setter私有,但是getter为publi ...
- 【linux基础-err】 tar命令-stdin: not in gzip format
problem gzip: stdin: not in gzip format tar: Error is not recoverable: exiting now 解决方法 最后发现下载的压缩文件有 ...
- APT攻击与银行
APT与传统攻击 APT:团队作战,拥有自研工具集,意图明确,技术高超,拥有政府或商业背景,潜伏期多达数年. 传统攻击:脚本小子,水平参差不齐,短期攻击,直接获取利益为目标. 攻击目标 APT攻击链 ...
- UML学习笔记:类图
UML学习笔记:类图 有些问题,不去解决,就永远都是问题! 类图 类图(Class Diagrame)是描述类.接口以及它们之间关系的图,用来显示系统中各个类的静态结构. 类图包含2种元素:类.接口, ...