【C++】非原创|统计代码覆盖率(一:C)
网络上php代码的覆盖率统计特别多,C/C++的不多见,大概是因为c/C++的收费?不知道= =
感谢原作者,原微博地址:http://www.cnblogs.com/turtle-fly/archive/2013/01/09/2851474.html
http://ltp.sourceforge.net/coverage/lcov.php demo
主要操作是:1 用gcov完成对c/c++文件的覆盖;2 通过lcov生成覆盖率报告;3 集成到jenkins的自动化case(需要自己做)
本章只写最简单的应用:编译单个c文件,生成lcov报告
一 搭建环境
我是直接在linux下运行程序,因此只需安装gcov和lcov环境即可
- 安装 C++ 编译环境
- yum list gcc-c++
- gcc-c++.x86_64
- rpm -q gcc-c++.x86_64 检查,若有该安装包则无需安装
- 若无则 yum list gcc-c++.x86_64
- vim 一个cpp文件
-
#include <iostream> int main() { std::cout << "Hello Wolrd!" << std::endl; return 0; }
- 编译为可执行文件 g++ HelloWorld.cpp -o 1.c
- 执行 ./1.c 即可
- 安装 gcov 环境
- 惭愧我服务器上有,所以没有安装。版本如下:gcov -v(跟gcc绑定的)
- 安装lcov环境:https://sourceforge.net/projects/ltp/ 可下载不同版本
-
cd /usr/local wget http://sourceforge.net/projects/ltp/files/Coverage%20Analysis/LCOV-1.12/lcov-1.12.tar.gz tar -xzvf lcov-1.12.tar.gz cd lcov-1.12 make install lcov -v 查看版本:lcov: LCOV version 1.12 即安装成功
不需要编译,直接安装。lcov, gendesc, genhtml, geninfo, genpng将被安装到/usr/bin目录。
二 编写一个简单的c文件。文件名 fib.c(斐波那契数列)
1 #include <stdio.h> 2 int fibonacci(int n); 3 4 int main () 5 { 6 int fib; 7 int n; 8 9 for (n = 0; n <= 10; n++) { 10 fib = fibonacci(n); 11 printf("fibonnaci(%d) = %d\n", n, fib); 12 } 13 14 return 0; 15 } 16 17 int fibonacci(int n) 18 { 19 int fib; 20 if (n <= 0) { 21 fib = 0; 22 } 23 else if (n == 1) { 24 fib = 1; 25 } 26 else { 27 fib = fibonacci(n -1) + fibonacci(n - 2); 28 } 29 30 return fib; 31 }
三 gcov覆盖代码
1. 编译:gcc -c fib.c -ftest-coverage -fprofile-arcs
检查发现生成了fib.gcno和fib.o文件,即正确
.gcno由-ftest-coverage产生,包含了重建基本块图和相应的块的源码的行号的信息。
2 链接:以下三者择一即可,生成可执行文件fib
gcc fib.o -o fib --coverage //我用的这个 gcc fib.o -o fib -lgcov gcc fib.o -o fib -fprofile-arcs
3 运行fib:./fib
生成gcda文件,.gcda是由加了-fprofile-arcs编译参数的编译后的文件运行所产生的,它包含了弧跳变的次数和其他的概要信息。见附1
4 生成gcov报告:gcov fib.c
生成的fib.c.gcov文件包含了代码覆盖的统计数据,数字代表每行代码被执行的次数及行号。
1 -: 0:Source:fib.c 2 -: 0:Graph:fib.gcno 3 -: 0:Data:fib.gcda 4 -: 0:Runs:1 5 -: 0:Programs:1 6 -: 1:#include <stdio.h> 7 -: 2: 8 -: 3:int fibonacci(int n); 9 -: 4: 10 1: 5:int main () 11 -: 6:{ 12 -: 7: int fib; 13 -: 8: int n; 14 -: 9: 15 12: 10: for (n = 0; n <= 10; n++) { 16 11: 11: fib = fibonacci(n); 17 11: 12: printf("fibonnaci(%d) = %d\n", n, fib); 18 -: 13: } 19 -: 14: 20 1: 15: return 0; 21 -: 16:} 22 -: 17: 23 453: 18:int fibonacci(int n) 24 -: 19:{ 25 -: 20: int fib; 26 453: 21: if (n <= 0) { 27 89: 22: fib = 0; 28 -: 23: } 29 364: 24: else if (n == 1) { 30 143: 25: fib = 1; 31 -: 26: } 32 -: 27: else { 33 221: 28: fib = fibonacci(n -1) + fibonacci(n - 2); 34 -: 29: } 35 -: 30: 36 453: 31: return fib; 37 -: 32:}
man
四 lcov整理覆盖率数据
1. 使用已生成的.gcon .gcda文件生成覆盖率数据fib.info文件 lcov -c -o fib.info -d .
其中:-c lcov的操作,表示要去捕获覆盖率数据
-o 输出文件,后面跟目标文件
-d 源文件.gcno .gcda所在文件夹,此处为'.'意为当前文件夹
[mobdev@ip-*** gtest]$lcov -c -o fib.info -d .
Capturing coverage data from .
Found gcov version: 4.8.3
Scanning . for .gcda files ...
Found 1 data files in .
Processing fib.gcda
Finished .info-file creation //表示成功
2. 生成html格式的报告: genhtml fib.info -o fib_result
即将文件fib.info生成html输出到fig_result文件夹内
[mobdev@ip-*** gtest]$genhtml fib.info -o fib_result Reading data file fib.info Found 1 entries. Found common filename prefix "***cppTest" Writing .css and .png files. Generating output. Processing file gtest/fib.c Writing directory view page. Overall coverage rate: lines......: 100.0% (12 of 12 lines) //代码逻辑行覆盖率 functions..: 100.0% (2 of 2 functions)//代码方法覆盖率
3 压缩文件下载到windows系统,并打开查看网页版
tar cvf fib_result.tar.gz fib_result/ sz fib_result.tar.gz //下载windows路径 在windows路径下,解压tar.gz文件,进入路径,在浏览器打开index.html如下图
五 问题
1 执行lcov命令时,报错"Out of memory!",生成的fib.info文件夹为空。是因为版本不匹配
解决:查看版本如下,需要更新lcov的版本。1.10以上的lcov才支持4.8的gcov
[user@ip-******* gtest]$gcov -v gcov (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9) Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. [user@ip-******* gtest]$lcov -v lcov: LCOV version 1.9
2 注意 gcc 只能编译 C 文件,编译 C++ 文件会报错
Fib.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
collect2: ld 返回 1
编写一个C++文件,则在操作的第二步时更换为如下文件及命令
Fib.cpp 文件(源码相同)
编译: g++ -c Fib.cpp -ftest-coverage -fprofile-arcs
链接: g++ Fib.o -o Fib --coverage
运行:./Fib
之后步骤相同,生成文件及各项检查均相同
附件为编译的各个文件的解析。
Linux平台代码覆盖率测试工具GCOV相关文件分析
附1 od -t x4 -w16 fib.gcda
http://www.linuxidc.com/Linux/2011-05/36537.htm