你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Go 的测试覆盖率

2021-12-2 14:04:06

这里填写标题

  • 1. Go 的测试覆盖率
    • 1.1. Go 的测试覆盖率
    • 1.2. 查看结果
      • 1.2.1. 保存收集的统计信息的文件
    • 1.3. 参考资料

1. Go 的测试覆盖率

测试覆盖率是一个术语, 用于统计通过运行程序包的测试多少代码得到执行。 如果执行测试套件导致 80%的语句得到了运行, 则测试覆盖率为 80%。

计算测试覆盖率的通常方法是埋点二进制可执行文件。 例如, GNU gcov 在二进制文件中设置执行分支断点。 当每个分支执行时, 断点被清除, 并且分支的目标语句被标记为 “被覆盖”。

这种方法是成功和广泛使用的。 Go 的早期测试覆盖工具甚至以相同的方式工作。但它有问题。 由于分析二进制文件的执行是很困难的, 所以很难实现。 它还需要将执行跟踪绑定回源代码的可靠方法, 这也可能是困难的。 那里的问题包括不正确的调试信息和诸如内联功能的问题, 使分析变得复杂。 最重要的是, 这种方法非常不具有可移植性。 对于每个机器架构需要重新编写, 在某种程度上, 可能对于每个操作系统都需要重新编写, 因为从系统到系统的调试支持差异很大。

Go 1.2 的发布引入了一个 test coverage 的新工具, 它采用了一种不寻常的方式来生成覆盖率统计数据, 这种方法建立在 Godoc 的技术的基础上。

1.1. Go 的测试覆盖率

示例代码如下:

func Size(a int) string {
  switch {
  case a < 0:
    return "negative"
  case a == 0:
    return "zero"
  case a < 10:
    return "small"
  case a < 100:
    return "big"
  case a < 1000:
    return "huge"
  }
  return "enormous"
}

测试代码如下:

type Test struct {
    in  int
    out string
}

var tests = []Test{
    {-1, "negative"},
    {5, "small"},
}

func TestSize(t *testing.T) {
    for i, test := range tests {
    size := Size(test.in)
    if size != test.out {
        t.Errorf("#%d: Size(%d)=%s; want %s", i, test.in, size, test.out)
    }
    }
}

执行代码覆盖率测试如下:

$ go test ./ -cover
ok  	mytest	(cached)	coverage: 42.9% of statements

1.2. 查看结果

1.2.1. 保存收集的统计信息的文件

上面的例子的测试覆盖率很差。 为了探索具体为什么, 需要 go test 写一个 coverage profile , 这是一个保存收集的统计信息的文件, 以便能详细地研究覆盖的细节。 这很容易做: 使用 -coverprofile 标志来指定输出的文件:

$ go test -coverprofile=size_coverage.out
PASS
coverage: 42.9% of statements
ok  	mytest	0.989s

注: -coverprofile 标志自动设置 -cover 来启用覆盖率分析。

测试与以前一样运行, 但结果保存在文件中。 要研究它们, 需要运行 test coverage tool。 一开始, 可以要求 覆盖率 按函数分解, 虽然在当前情况下没有太多意义, 因为只有一个函数:

$ go tool cover -func=size_coverage.out
mytest/main.go:3:	Size		42.9%
total:			(statements)	42.9%

查看的更有趣的方式是获取覆盖率信息注释的源代码 的 HTML 展示。 该显示由 -html 标志调用:

go tool cover -html=size_coverage.out

运行此命令时, 浏览器将弹出窗口, 已覆盖 (绿色), 未覆盖(红色) 和 未埋点(灰色)。 下面是一个屏幕截图:

在这里插入图片描述

有了这个信息页, 问题变得很明显: 上面忽略了几个 case 的测试! 可以准确地看出具体是哪一个, 这样可以轻松地提高的测试覆盖率。

1.3. 参考资料

  • https://www.elastic.co/cn/blog/code-coverage-for-your-golang-system-tests