测试覆盖率是代码质量的一个非常重要的衡量指标。

在 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

更多测试覆盖率工具包

goconvey

安装

1
go install github.com/smartystreets/goconvey

进入项目目录执行

1
$GOPATH/bin/goconvey

执行成功后,在浏览器中打开:http://localhost:8080

网页特征说明 Graphical feature tour

gocov-html

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

gotest

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 指定单元测试文件或包路径,多个空格隔开

参考