golang 单元测试和性能测试

发表于:2023-2-03 09:03

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:老A技术联盟    来源:稀土掘金

  单元测试
  单元测试(Unit Tests, UT) 是一个优秀项目不可或缺的一部分,特别是在一些频繁变动和多人合作开发的项目中尤为重要。你或多或少都会有因为自己的提交,导致应用挂掉或服务宕机的经历。比如我就曾经就因为打印了sql,而忘记关闭,导致所有的接口异常(允悲)。还有就是如果你优化了一些代码逻辑,优化了某个函数。那么我们怎么保证我们的正确性呢?那么几个测试用例或许就可以解决这个问题。
  测试文件的命名
  go语言是支持单元测试的,测试文件是_test.go结尾的文件名。
  测试用例的命名
  测试用例名称一般命名为 Test 加上待测试的方法名。比如TestAdd(),测试用的参数有且只有一个,在这里是 t *testing.T。
  简单入门
  我们来写一个Add函数,创建文件add.go。
  package main
  import "fmt"
  func main() {
  sum := Add(1, 2)
  fmt.Println(sum)
  }
  func Add(a int, b int) int {
  return a + b
  }
  我们在add.go目录下创建一个add_test.go的测试文件。
  package main
  import (
  "testing"
  )
  func TestAdd(t *testing.T) {
  testData := []struct {
  a int
  b int
  c int
  }{
  {1, 2, 3},
  {4, 5, 9},
  {50, 5, 5},
  }
  ans := 0
  for _, data := range testData {
  if ans = Add(data.a, data.b); ans != data.c {
  t.Errorf("%d + %d expected %d,but %d got", data.a, data.b, data.c, ans)
  }
  }
  }
  我们先来认识一下ide调试工具,当然这些调试我们在命令也是可以运行的:
  ·Run 执行脚本
  · Debug 开启Debug模式
  · coverprofile 代码覆盖率
  · CPU Profiler cup分析
  · Memory Profiler 内存分析 对象、堆的分析和内存泄漏等
  · Blocking Profiler 记录 goroutine的阻塞情况,等待和同步情况,timer/channel通讯等各项细节
  · Mutex Profiler 互斥锁分析,包括各种竞争情况
  我通过ide运行一下:
  我们也可以使用ide的debug功能打断点调试:
  命令行测试,首先我们进入add.go目录:
  代码覆盖率
  IDE调试:
  我们使用命令行再试一下:
  zhangguofu@zhangguofudeMacBook-Pro add (master) $ go test -coverprofile=c.out 
  --- FAIL: TestAdd (0.00s)
      add_test.go:20: 50 + 5 expected 5,but 55 got
  FAIL
  coverage: 33.3% of statements
  exit status 1
  FAIL    goapp/src/learngo/add   0.502s
  zhangguofu@zhangguofudeMacBook-Pro add (master) $ ls
  add.go      add_test.go c.out
  zhangguofu@zhangguofudeMacBook-Pro add (master) $ cat c.out
  mode: set
  goapp/src/learngo/add/add.go:5.13,8.2 2 0
  goapp/src/learngo/add/add.go:10.28,12.2 1 1
  我们发现多了一个c.out 文件,但是里面的内容我们看不太懂,我们借助工具go tool cover ,查看代码覆盖的相关命令帮助。
  我们使用` go tool cover -html=c.out``,此时会打开一个html页面,上面标注了我们代码覆盖的情况。
  性能测试
  ·我们通过一个获取最长不重复字符串函数来测试一下性能
  · 函数代码 在add.go文件中
  /**
  最大字符串不重复
  */
  func Repeat(s string) int {
  //保持最大不重复串
  lastOccur := make(map[string]int)
  start := 0
  max := 0
  for k, v := range []rune(s) {
  if index, ok := lastOccur[string(v)]; ok && start <= index {
  start = index + 1
  }
  if max < k-start+1 {
  max = k - start + 1
  }
  lastOccur[string(v)] = k
  }
  return max
  }
  性能测试代码 在add_test.go文件中:
  func BenchmarkRepeat(b *testing.B) {
  str := "不经历风雨,怎么见彩虹?没有人能随随便便成功"
  data := struct {
  content string
  res     int
  }{
  str,
  17,
  }
  for i := 0; i < b.N; i++ {
  if len := Repeat(data.content); len != 17 {
  b.Error("the program is wrong")
  }
  }
  }
  结果是3ms左右,我们加长一点看看:
  func BenchmarkRepeat(b *testing.B) {
  str := "不经历风雨,怎么见彩虹?没有人能随随便便"
  for i := 0; i < 20; i++ {
  str += str
  }
  b.Logf("the len of str is %d", len(str))
  b.ResetTimer() //忽略上面的计算时间
  for i := 0; i < b.N; i++ {
  Repeat(str)
  }
  }
  我们发现对于计算6m文件中的不重复字符串,程序执行了大概是16s左右,这个感觉很慢了,对不对,但是我们想看程序是时间花在哪里了。
  和代码覆盖率的命令类似。我执行命令:
  zhangguofu@zhangguofudeMacBook-Pro add (master) $ go test -bench . -cpuprofile  cpu.out
  goos: darwin
  goarch: amd64
  pkg: goapp/src/learngo/add
  BenchmarkRepeat-8              1        1541179761 ns/op
  --- BENCH: BenchmarkRepeat-8
      add_test.go:33: the len of str is 62914560
  PASS
  ok      goapp/src/learngo/add   2.077s
  zhangguofu@zhangguofudeMacBook-Pro add (master) $ ls
  add.go      add.test    add_test.go c.out       cpu.out
  zhangguofu@zhangguofudeMacBook-Pro add (master) $ less cpu.out  
  "cpu.out" may be a binary file.  See it anyway? 
  发现生成的cpu.out 是一个二进制文件,我们使用go tool pprof cpu.out 查看,进入交互模式。
  我输入web格式的,报错说需要安装Graphviz ,那就安装吧。
  再次输入 go tool pprof cpu.out 输入web没有报错了,但是此处我碰到一个个问题。就是我的虚拟机(mac上面装的win10)会默认打开svg 文件,很烦人。
  解决方式:
  并且设置谷歌浏览器为默认打开方式:
  最终,我们打开了这个文件,这里面箭头越粗,代表花费的时间越长,我们可以根据结果 对我们的程序进行优化,比如在这里,我们看到是string encode decode 很浪费时间,那么我们是不是可以选择更合适的数据类型来存储我们的数据呢,比如我们存的是 abc我爱中国 ,那么再计算中,来回转换是很麻烦的,我们是不是可以转换为int32来计算呢。
  golang的单元测试和性能测试就先到这里了。喜欢可以点赞哦!!
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号