文章 测试覆盖度

定义:Test coverage(测试覆盖度)用于衡量一个包中的代码被测试用例覆盖的程度。
如果运行所有的测试用例能够触发包中80%的代码运行,我们就认为测试覆盖度为80%。

通常情况下,要计算测试覆盖率,需要对执行文件进行二进制拦截,比如gcov工具:通过在每个逻辑分支之后添加一个断点,来标记这个分支是否被执行到。这种基于二进制拦截的方法移植性不够好,需要针对不同CPU架构来实现。

go test -cover
package size

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"
}

重写后:

func Size(a int) string {
    GoCover.Count[0] = 1
    switch {
    case a < 0:
        GoCover.Count[2] = 1
        return "negative"
    case a == 0:
        GoCover.Count[3] = 1
        return "zero"
    case a < 10:
        GoCover.Count[4] = 1
        return "small"
    case a < 100:
        GoCover.Count[5] = 1
        return "big"
    case a < 1000:
        GoCover.Count[6] = 1
        return "huge"
    }
    GoCover.Count[1] = 1
    return "enormous"
}
GoCover.Count[]
go test -covergo test -coverprofile=cover.out
go tool cover -html=cover.out
热力图
go test -covermode=set|count|atomic-covermode
  • set: 默认模式,统计是否执行
  • count: 计数
  • atomic: count的并发安全版本,仅当需要精确统计时使用
fmt
$ go test -covermode=count -coverprofile=count.out fmt
ok      fmt     1.320s  coverage: 95.1% of statements


将鼠标悬浮在代码块上可以看到具体执行的数据。

go tool cover -func=count.out
$ go tool cover -func=count.out
fmt/format.go: init              100.0%
fmt/format.go: clearflags        100.0%
fmt/format.go: init              100.0%
fmt/format.go: computePadding     84.6%
fmt/format.go: writePadding      100.0%
fmt/format.go: pad               100.0%
...
fmt/scan.go:   advance            96.2%
fmt/scan.go:   doScanf            96.8%
total:         (statements)       91.7%

也许从这些测试中可以得到关于性能优化的提示。