经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
使用Go进行单元测试的实现
来源:jb51  时间:2019/11/7 20:22:26  对本文有异议

简介

日常开发中, 测试是不能缺少的.

Go 标准库中有一个叫做 testing 的测试框架, 可以用于单元测试和性能测试.

它是和命令 go test 集成使用的.

测试文件是以后缀 _test.go 命名的, 通常和被测试的文件放在同一个包中.

单元测试

单元测试的格式形如:

  1. func TestAbs(t *testing.T) {
  2. got := Abs(-1)
  3. if got != 1 {
  4. t.Errorf("Abs(-1) = %d; want 1", got)
  5. }
  6. }

在 util 目录下创建一个文件 util_test.go, 添加一个单元测试:

  1. package util
  2.  
  3. import "testing"
  4.  
  5. // 普通的测试
  6. func TestGenShortID(t *testing.T) {
  7. shortID, err := GenShortID()
  8. if shortID == "" || err != nil {
  9. t.Error("GenShortID failed")
  10. }
  11. }
  12.  

然后, 在根目录下运行 go test -v ./util/, 测试结果如下:

  1. root@592402321ce7:/workspace# go test -v ./util/
  2. === RUN TestGenShortID
  3. --- PASS: TestGenShortID (0.00s)
  4. PASS
  5. ok tzh.com/web/util 0.006s

性能测试

性能测试的结果形如:

  1. func BenchmarkHello(b *testing.B) {
  2. for i := 0; i < b.N; i++ {
  3. fmt.Sprintf("hello")
  4. }
  5. }

在 util_test.go 添加性能测试:

  1. // 性能测试
  2. func BenchmarkGenShortID(b *testing.B) {
  3. for i := 0; i < b.N; i++ {
  4. GenShortID()
  5. }
  6. }

运行结果如下(使用 --run=none 避免运行普通的测试函数, 因为一般不可能有函数名匹配 none):

  1. root@592402321ce7:/workspace# go test -v -bench="BenchmarkGenShortID$" --run=none ./util/
  2. goos: linux
  3. goarch: amd64
  4. pkg: tzh.com/web/util
  5. BenchmarkGenShortID-2 507237 2352 ns/op
  6. PASS
  7. ok tzh.com/web/util 1.229s

这说明, 平均每次运行 GenShortID() 需要 2352 纳秒.

性能分析

运行测试的时候, 可以指定一些参数, 生成性能文件 profile.

  1. -blockprofile block.out
  2. Write a goroutine blocking profile to the specified file
  3. when all tests are complete.
  4. Writes test binary as -c would.
  5.  
  6. -blockprofilerate n
  7. Control the detail provided in goroutine blocking profiles by
  8. calling runtime.SetBlockProfileRate with n.
  9. See 'go doc runtime.SetBlockProfileRate'.
  10. The profiler aims to sample, on average, one blocking event every
  11. n nanoseconds the program spends blocked. By default,
  12. if -test.blockprofile is set without this flag, all blocking events
  13. are recorded, equivalent to -test.blockprofilerate=1.
  14.  
  15. -coverprofile cover.out
  16. Write a coverage profile to the file after all tests have passed.
  17. Sets -cover.
  18.  
  19. -cpuprofile cpu.out
  20. Write a CPU profile to the specified file before exiting.
  21. Writes test binary as -c would.
  22.  
  23. -memprofile mem.out
  24. Write an allocation profile to the file after all tests have passed.
  25. Writes test binary as -c would.
  26.  
  27. -memprofilerate n
  28. Enable more precise (and expensive) memory allocation profiles by
  29. setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
  30. To profile all memory allocations, use -test.memprofilerate=1.
  31.  
  32. -mutexprofile mutex.out
  33. Write a mutex contention profile to the specified file
  34. when all tests are complete.
  35. Writes test binary as -c would.
  36.  
  37. -mutexprofilefraction n
  38. Sample 1 in n stack traces of goroutines holding a
  39. contended mutex.

使用下面的命令, 生成 CPU 的 profile:

  1. go test -v -bench="BenchmarkGenShortID$" --run=none -cpuprofile cpu.out ./util/

当前目录下, 应该会生成 cpu.out 文件和 util.test 文件.

使用下面的命令, 观察耗时操作:

  1. # 进入交互模式
  2. go tool pprof cpu.out
  3. top

安装 Graphviz 后可以生成可视化的分析图.

  1. apt install graphviz
  2. go tool pprof -http=":" cpu.out

测试覆盖率

  1. root@592402321ce7:/workspace# go test -v -coverprofile=cover.out ./util/
  2. === RUN TestGenShortID
  3. --- PASS: TestGenShortID (0.00s)
  4. PASS
  5. coverage: 9.1% of statements
  6. ok tzh.com/web/util 0.005s coverage: 9.1% of statements
  7.  
  8. root@592402321ce7:/workspace# go tool cover -func=cover.out
  9. tzh.com/web/util/util.go:12: GenShortID 100.0%
  10. tzh.com/web/util/util.go:17: GetReqID 0.0%
  11. tzh.com/web/util/util.go:22: TimeToStr 0.0%
  12. tzh.com/web/util/util.go:30: GetTag 0.0%
  13. total: (statements) 9.1%

使用 -coverprofile=cover.out 选项可以统计测试覆盖率.使用 go tool cover -func=cover.out 可以查看更加详细的测试覆盖率结果,
统计每个函数的测试覆盖率.

总结

测试是开发中非常重要的一个环节, 用于保证软件质量, 切不可偷懒.

当前部分的代码

作为版本 v0.15.0

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号