测试覆盖率是代码质量的一个非常重要的衡量指标。
在 golang 中可以使用 go test 运行单元测试,并输出代码测试覆盖率报告。
进入项目目录,执行下面命令,输出当前目录下所有package的coverage百分比
1
|
go test -v -cover -covermode=count -coverprofile=coverage.out ./...
|
输出指定package目录的覆盖率:
1
|
go test -v -cover -covermode=count -coverprofile=coverage.out -coverpkg=./... ./model ./pkg
|
参数covermod支持三种模式:
-covermode set,count,atomic
Set the mode for coverage analysis for the package[s]
being tested. The default is “set” unless -race is enabled,
in which case it is “atomic”.
The values:
set: bool: does this statement run?
count: int: how many times does this statement run?
atomic: int: count, but correct in multithreaded tests;
significantly more expensive.
Sets -cover.
有使用 gomonkey 时,必须禁用 golang 编译器的内联优化,不然函数被内联之后,就找不到接缝了,stub 无法进行。通过 go test 的时候带上 -gcflags=all=-N -l
来禁用内联优化。
1
|
go test -v -cover -gcflags=all=-N -l -covermode=count -coverprofile=coverage.out ./...
|
或者在函数或方法增加如下注释,这样编译器就不会对其进行内联处理。
1
2
3
4
|
//go:noinline
func() Add(a, b int) int {
return a + b
}
|
覆盖率报告html可视化:
1
|
go tool cover -html=coverage.out
|
执行上面命令,即可以html的方式展示代码覆盖率,其中红色显示的为未覆盖到的代码逻辑。
查看每个函数的覆盖率报告
1
|
go tool cover -func=coverage.out
|
更多test命令参数详解 testing flags
更多测试覆盖率工具包
安装
1
|
go install github.com/smartystreets/goconvey
|
进入项目目录执行
执行成功后,在浏览器中打开:http://localhost:8080
网页特征说明
Make pretty HTML output from gocov, a coverage testing tool for Go
安装
1
2
3
|
go install github.com/axw/gocov/gocov@latest
go install github.com/matm/gocov-html/cmd/gocov-html@latest
|
使用示例,输出标准库中strings包的覆盖率报告
1
2
|
$ gocov test strings | gocov-html > strings.html
ok strings 0.700s coverage: 98.1% of statements
|
go test with colors
安装
1
|
$ go get -u github.com/rakyll/gotest
|
使用
1
|
$ gotest -v github.com/jonasbn/go-test-demo
|
还可以通过环境变量设置输出颜色
1
|
$ GOTEST_PALETTE="magenta,white"
|
The output will have magenta for failed cases, white for success. Available colors: black, hiblack, red, hired, green, higreen, yellow, hiyellow, blue, hiblue, magenta, himagenta, cyan, hicyan, white, hiwhite.
生成覆盖率报告脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#!/bin/bash
workDir=$(cd `dirname $0`;cd ../; pwd)
currtime=`date +"%Y%m%d_%H%M%S"
module=`go list -m`
coverpkg=${module}
names=()
while [ -n $1 ]; do
case "$1" in
-p)
coverpkg=${module}/${2}
shift ;;
-f)
for arg in "$@"; do
if [ "$arg" == "-f" ]; then
continue
fi
names+=("${module}/$arg")
done
shift ;;
-h)
echo "usage:"
echo "sh ./build/cover.sh [-p coverpkg] [-f filename1 filename2]"
exit 0 ;;
*)
break ;;
esac
shift
done
# 默认当前项目全部目录
if [ ${#names[@]} -eq 0 ]; then
files=${module}/...
names+=("${files}")
fi
coverout=${workdir}/cover.${currtime}.out
funcout=${workdir}/func.${currtime}.out
htmlout=${workdir}/cover.${currtime}.html
go test -v -cover -gcflags=all=-N -l -covermode=count -coverprofile=${coverout} -coverpkg=${coverpkg} ${names[@]}
go tool cover -func=${coverout} -o ${funcout}
go tool cover -html=${coverout} -o ${htmlout}
|
使用 -p 指定 coverpkg 参数,-f 指定单元测试文件或包路径,多个空格隔开
参考