最近在跟一个推荐系统引擎相关功能的测试,做过相关测试的同学应该知道引擎可是整套系统的核心,如果引擎系统挂了或者出现了严重bug对整个系统的影响可是无法估量的。所以为了保证引擎系统能够稳定的运行必须采用足够多的手段,所以测试中代码覆盖率可以作位一种测试是否全面的衡量标准。
由于之前没有做过相关方面的工作,所以要从头开始研究,这里把最近学习的成果做一个简单的介绍。
一、环境准备:
我是直接在Ubuntu 下运行程序,因此只需安装gcov和lcov环境即可:
$ sudo apt-get install gcov
检查是否安装成功:gcov -v
$ sudo apt-get install lcov:
检查是否安装成功:lcov -v
二、简单示例:
写一个简单的c++示例代码:
#include<stdio.h>
int Add(inta,int b);
int Sub(inta,int b);
int Mul(inta,int b);
int Div(inta,int b);
int main ()
{
int a=10;
int b=5;
printf("%d + %d = %d\n", a, b,Add(a, b));
return 0;
}
int Add(int a,int b)
{
return (a+b);
}
int Sub(int a,int b)
{
return (a-b);
}
int Mul(int a,int b)
{
return (a*b);
}
// 不做异常处理
int Div(int a,int b)
{
return (a/b);
}
正常执行一下看看运行结果:
接下来我们看看测试的代码覆盖率的实际效果
1. 编译
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# gcc -ctest.c -ftest-coverage -fprofile-arcs
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# ls
test.c test.gcno test.o
除了test.o 之外,还生成了 test.gcno 的话,成功了
.gcno是由-ftest-coverage产生的,它包含了重建基本块图和相应的块的源码的行号的信息。
2.生成可执行文件
gcc test.o -o test --coverage //我用的这个
gcc test.o -o test -lgcov
gcc test.o -o test -fprofile-arcs
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# gcc test.o-o test –coverage
执行完的效果如下:
运行后的效果如下:
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# ./test
10 + 5 = 15
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# ls
test test.c test.gcda test.gcno test.o
生成gcda文件,.gcda是由加了-fprofile-arcs编译参数的编译后的文件运行所产生的
3、生成测试结果:
执行结果如下:
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new#gcov test.c
File 'test.c'
Lines executed:53.85% of 13
Creating 'test.c.gcov'
生成的test.c.gcov文件包含了代码覆盖的统计数据,数字代表每行代码被执行的次数及行号。被标记为#####的代码行就是没有被执行过的,代码覆盖的信息是正确的,但是让人去读这些文字,实在是一个杯具。不用担心,开始咱们安装的另一个工具lcov还没大显身手嗯,他的本领就是用程序解析这些晦涩的字符,输出一个完美的html报告给开发
-: 0:Source:test.c
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:int Add(int a,int b);
-: 4:int Sub(int a,int b);
-: 5:int Mul(int a,int b);
-: 6:int Div(int a,int b);
-: 7:
-: 8:
1: 9:int main ()
-: 10:{
1: 11: int a=10;
1: 12: int b=5;
-: 13:
1: 14: printf("%d + %d = %d\n", a, b,Add(a, b));
-: 15:
1: 16: return 0;
-: 17:}
-: 18:
-: 19:
1: 20:int Add(int a, int b)
-: 21:{
1: 22:return (a+b);
-: 23:}
-: 24:
-: 25:
#####: 26:int Sub(int a, int b)
-: 27:{
#####: 28:return (a-b);
-: 29:}
-: 30:
-: 31:
#####: 32:int Mul(int a, int b)
-: 33:{
#####: 34:return (a*b);
-: 35:}
-: 36:
-: 37:
-: 38:// 不做异常处理
#####: 39:int Div(int a, int b)
-: 40:{
#####: 41:return (a/b);
-: 42:}
-: 43:
至于 gcov 的更多选项,例如 -b 分支覆盖 -f 函数覆盖,就 man 吧
4、LCOV 使用
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new#lcov -c -o test.info -d .
Capturingcoverage data from .
Found gcov version:4.9.2
Scanning . for.gcda files ...
Found 1 datafiles in .
Processingtest.gcda
Finished .info-filecreation
简单解释一下三个选项
-c: lcov 的一个操作,表示要去捕获覆盖率数据
-o: 输出文件
-d: .gcno .gcda 所在的文件夹,注意这里有个“.”,是从当前文件夹中获取数据的
生成最终的html结果:
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# genhtmltest.info -o test_result
Reading data file test.info
Found 1 entries.
Found common filename prefix "/home"
Writing .css and .png files.
Generating output.
Processing file gcov_test_new/test.c
Writing directory view page.
Overall coverage rate:
lines......: 53.8% (7of 13 lines)
functions..: 40.0% (2of 5 functions)
从以上结果可以看出覆盖率分为行覆盖率53.8% 函数覆盖率40.00%(把main函数也算进去了)
执行后多了一个文件夹:
root@guozhenhua-OptiPlex-7010:/home/gcov_test_new# ls
test test.c test.gcda test.gcno test.info test.o test_result
将生成的代码文件转移到apache下查看效果如下:
红色部分是未执行到的代码,蓝色部分是被执行的代码,前的数字是被执行的次数,而且最上面还有总的行覆盖率和函数覆盖率
后期还会分享so文件的覆盖率和外部传参的覆盖率