golang 单元测试 (https://github.com/stayfoo/stayfoo-hub)

stayfoo · · 783 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

> 我的 golang 开发笔记:https://github.com/stayfoo/stayfoo-hub ## 单元测试 一般有三类测试:功能测试(test)、性能测试(benchmark,也叫基准测试)、示例测试(example)。 ### 编写规则 测试源码文件名称要求:`被测试源码文件的名称_test.go`, eg:要对 `demo.go` 进行测试,测试文件就是 `demo_test.go` 。 测试函数的名称和签名规定: - `test` 测试函数,名称必须以 `Test` 为前缀; 只能有一个参数, 且参数类型:`*testing.T` 。 - `benchmark` 测试函数,名称必须以 `Benchmark` 为前缀; 只能有一个参数,且类型为:`*testing.B`。 - `example` 测试函数, 名称必须以 `Example` 为前缀;对参数列表没有强制规定。(与功能测试相比,更关注程序打印出来的内容) ### go test `go test` 使测试代码执行,需要测试文件编写遵循上面的规则。 `go test` 执行的主要流程: ``` === RUN TestFail --- PASS: TestFail (0.00s) main_test.go:49: Failed. PASS ok code/test 0.006s # ok: 说明测试结果和预期一样 # code/test: 测试的代码包路径 # 0.006s : 此次对该代码包的测试所耗费的时间 ``` - 参数 `-run` ``` #执行被测试包中的所有功能测试函数 go test #同 go test go test -run '' #可以是一个函数的名字 go test -run=TestHello #匹配部分函数名, 匹配以 TestHel 开头的测试函数, eg: TestHello go test -run=Hel #同上 go test -run Hel ``` 不执行任何功能测试函数 `-run ^$` ``` go test -run ^$ # 和其他参数一起使用,比如只想执行 benchmark 函数: go test -run ^$ -bench . ``` 测试代码: ```go func TestHello2(t *testing.T) { t.Run("A=1", func(t *testing.T) { fmt.Println("hello2 is A=1") }) t.Run("A=2", func(t *testing.T) { fmt.Println("hello2 is A=2") }) t.Run("B=1", func(t *testing.T) { fmt.Println("hello2 is B=1") }) } ``` ``` # 匹配运行 所有 TestHello 开头的测试函数,以及测试函数内部 A= 的子测试用例 go test -run Hello/A= # 匹配运行 所有的测试函数,以及测试函数内部 A=1 的子测试用例 go test -run /A=1 ``` - 缓存: ``` # 查看缓存目录的路径: go env GO CACHE # 手动删除所有缓存 go clean -cache # 删除所有的测试结果缓存;不会删除任何构建结果缓存。 go clean -testcache ``` ``` #设置环境变量 GODEBUG # go 命令绕过任何的缓存数据,真正执行操作并重新生成所有结果,然后再去检查新的结果与现有的缓存数据是否一致 gocacheverify=1 ``` ### Benchmark `go test` 加上 `-bench=.` 才会执行性能测试。 ``` # 值 . 表示执行任意名称的性能测试函数 go test -bench=. 还可以是一个函数的名字 或者前面一部分: go test -bench=BenchmarkGetStore go test -bench=BenchmarkGetS ``` - 只执行 Benchmark ``` # 和其他参数一起使用,比如只想执行 benchmark 函数: go test -run ^$ -bench . ``` - 运行结果解读 ```go func BenchmarkHandleData(b *testing.B) { for i:=0; i<b.N; i++ { HandleData() } } ``` ``` go test -run ^$ -bench . goos: darwin goarch: amd64 BenchmarkHandleData-4 3000 401651 ns/op PASS ok command-line-arguments 1.259s ``` ``` #1. 运行的性能测试函数:BenchmarkHandleData 被测试的函数是:HandleData #2. 运行时使用的最大 P 数量为 4 #3. 3000 是指被测函数 HandleData 的执行次数 #4. 401651 ns/op = 性能测试函数执行时间 / 被测函数执行次数; 单次执行被测函数的平均耗时为 401651 纳秒; BenchmarkHandleData-4 3000 401651 ns/op ``` > 最大 P 数量 ? > > P:processor ,是 G 和 M的中介,使 G 与 M 对接并得到真正的运行。Go运行时系统中,P越多,承载 G 的队列越多, G可运行的越多(最大P代表同时运行goroutine的能力)。 每一条承载 G 的队列,会不断的把可运行的 G 给空闲的 M 去对接。对接完成,被对接的 G 就真正运行在操作系统的内核级线程上了。每条队列之间会有联系,但都是独立运作的。 > > G: goroutine ,协程 > > M: machine ,代表着系统级线程,即操作系统内核级别的线程 > 使用 `go test -cpu` 来设置最大 P 数量. 或者 调用 `runtime.GOMAXPROCS` 函数改变最大 P 数量。模拟被测试程序在不同计算能力的计算机中的表现。 ### 一些函数 #### t.Log() 打印常规的测试日志:(当测试成功的时候,不会打印) ``` t.Log() t.Logf() ``` 可以使用 `-v` 打印所有的常规测试日志: ``` go test -v ``` #### t.Fail() ``` func TestFail(t *testing.T) { t.Fail() //t.FailNow() //会让函数立即终止,该行代码之后的所有代码都不会执行。 t.Log("Failed.") } ``` 对于失败测试的结果, `go test` 命令并不会进行缓存。 测试失败,会把失败函数里面的常规日志打印出来。(`t.Log("Failed.")`) #### t.Error() `t.Error()` 相当于 `t.Fail()` + `t.Log()` 。 ``` //相当于 t.Fail() + t.Log("Failed log.") t.Error("Failed log.") ``` `t.Errorf()` 相当于 `t.Fail()` + `t.Logf()` 。 ``` //相当于 t.Fail() + t.Log("Failed log.") t.Errorf("Failed log.") ``` #### t.Fatal() 打印失败错误日志之后立即终止当前测试函数的执行,测试失败。 相当于最后调用了 `t.FailNow()` 。 ``` t.Fatal("Failed log.") t.Fatalf("Failed log.") ``` > 我的 golang 开发笔记:https://github.com/stayfoo/stayfoo-hub

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

783 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传