【Go语言】代码覆盖测试(gcov)
GCOV
gcov是gcc提供的代码覆盖测试工具,它的测试结果体现2个指标。
- 每行代码执行的频率
- 实际上执行了几行代码
对于执行频率高的代码,需要重点优化;而没有被执行的代码,需要检查是否存在BUG,或是无用代码。
示例工程
一共有3个代码文件:
- calc/main.go 主程序
- simplemath/add.go 提供Add()函数
- simplemath/sqrt.go 提供Sqrt()函数
water@ubuntu-desktop:~/Workplace/golang/helloprj$ tree
.
├── bin
├── pkg
│ ├── gccgo_linux_amd64
│ └── linux_amd64
└── src
├── calc
│ └── main.go
└── simplemath
├── add.go
└── sqrt.go
7 directories, 4 files
water@ubuntu-desktop:~/Workplace/golang/helloprj$
simplemath/add.go
package simplemath
func Add(a int64, b int64) int64 {
return a + b
}
simplemath/sqrt.go
package simplemath
import "math"
func Sqrt(i int) int {
v := math.Sqrt(float64(i))
return int(v)
}
calc/main.go
package main
import "fmt"
import "simplemath"
// 用for循环计算斐波那契数
func fibonacci(n int64) (int64) {
var res int64 = 0
var tmp int64 = 1
var idx int64 = 0
for ; idx < n; idx++ {
res = simplemath.Add(res, tmp)
res, tmp = tmp, res
}
return res
}
// 用递归方法计算斐波那契数
func fibonacci_r(n int64) (int64) {
if n < 1 {
return 0
} else if n < 3 {
return 1
}
lhs := fibonacci_r(n - 1)
rhs := fibonacci_r(n - 2)
ret := simplemath.Add(lhs, rhs)
return ret
}
// 计算斐波那契数,并打印出来
func main() {
num := fibonacci(30)
fmt.Println("Result:", num)
res := fibonacci_r(30)
fmt.Println("Result:", res)
}
编译代码(生成gcno文件)
Makefile
all: simplemath calc
simplemath:
gccgo -c -o simplemath.o $(FLAGS) src/simplemath/add.go src/simplemath/sqrt.go
ar r pkg/gccgo_linux_amd64/libsimplemath.a simplemath.o
rm simplemath.o
calc:
gccgo -o bin/calc $(FLAGS) -L pkg/gccgo_linux_amd64 src/calc/main.go -lsimplemath
clean:
rm pkg/gccgo_linux_amd64/libsimplemath.a
rm bin/calc
使用"–coverage"编译参数
[user@host goprj]$ FLAGS="--coverage" make
gccgo -c -o simplemath.o --coverage src/simplemath/add.go src/simplemath/sqrt.go
ar r pkg/gccgo_linux_amd64/libsimplemath.a simplemath.o
ar: creating pkg/gccgo_linux_amd64/libsimplemath.a
rm simplemath.o
gccgo -o bin/calc --coverage -L pkg/gccgo_linux_amd64 src/calc/main.go -lsimplemath
编译后,在当前目录生成gcno文件
[user@host goprj]$ ls -lh *.gcno
-rw-rw-r-- 1 root root 5.7K Jan 1 00:00 main.gcno
-rw-rw-r-- 1 root root 792 Jan 1 00:00 simplemath.gcno
运行程序(生成gcda文件)
运行后,在当前目录生成gcda文件
[user@host goprj]$ bin/calc
Result: 832040
Result: 832040
[user@host goprj]$ ls -lh *.gcda
-rw-rw-r-- 1 root root 640 Jan 1 00:00 main.gcda
-rw-rw-r-- 1 root root 120 Jan 1 00:00 simplemath.gcda
gcov(生成gcov文件)
[user@host goprj]$ gcov *.gcda
main.gcno:version 'B02*', prefer 'A93*'
main.gcda:version 'B02*', prefer version 'A93*'
simplemath.gcno:version 'B02*', prefer 'A93*'
simplemath.gcda:version 'B02*', prefer version 'A93*'
File 'src/calc/main.go'
Lines executed:95.65% of 23
Creating 'main.go.gcov'
File 'src/simplemath/sqrt.go'
Lines executed:0.00% of 3
Creating 'sqrt.go.gcov'
File 'src/simplemath/add.go'
Lines executed:100.00% of 2
Creating 'add.go.gcov'
[user@host goprj]$ ls -lh *.gcov
-rw-rw-r-- 1 root root 340 Jan 1 00:00 add.go.gcov
-rw-rw-r-- 1 root root 1.8K Jan 1 00:00 main.go.gcov
-rw-rw-r-- 1 root root 346 Jan 1 00:00 sqrt.go.gcov
lcov(生成info文件)
[user@host goprj]$ lcov -c -d ./ -o calc.coverage
Finished .info-file creation
[user@host goprj]$ ls -lh calc.coverage
-rw-rw-r-- 1 root root 1.4K Jan 1 00:00 calc.coverage
genhtml(可视化成html)
[user@host goprj]$ genhtml -o calc.coverage.html calc.coverage
Reading data file calc.coverage
Found 3 entries.
Writing .css and .png files.
Generating output.
Processing file calc/main.go
Processing file simplemath/sqrt.go
Processing file simplemath/add.go
Writing directory view page.
Overall coverage rate:
lines......: 85.7% (24 of 28 lines)
functions..: 50.0% (5 of 10 functions)
结果分析
main.go.gcov
add.go.gcov
sqrt.go.gcov
递归算法真的很不适合斐波那契数呀~