GCOV是一个测试C/C++代码覆盖率的工具,使用它可以看出哪些代码被执行了,被执行的次数和时间。
GCOV随着gcc安装,不需要我们另外再进行安装,gcov的使用如下。
想要用 gcov 收集代码覆盖信息, 需要在编译代码的时候加上这 2 个选项 -fprofile-arcs -ftest-coverage,编译后会生成gcno文件。
g++ -fprofile-arcs -ftest-coverage hello.cpp -o hello
#include
using namespace std;
int main()
{
cout << "Hello, World!";
return 0;
}
修改Makefile文件,补充以下内容
GCOV_FLAGS=-fprofile-arcs -ftest-coverage
CFLAGS+=$(GCOV_FLAGS)
LDFLAGS+=-lpthread $(GCOV_FLAGS)
CXXFLAGS+=$(GCOV_FLAGS)
CPPFLAGS+=$(GCOV_FLAGS)
在configure过程中,增加以下参数:
LDFLAGS+='-fprofile-arcs' CFLAGS+='-fprofile-arcs -ftest-coverage' CXXFLAGS+='-fprofile-arcs -ftest-coverage' CPPFLAGS+='-fprofile-arcs -ftest-coverage' ./configure --without-system-libs --without-system-headers LIBS=-lgcov
之后make,与正常编译一样。
运行相应的case可以看到生成了gcda文件,这时可以使用命令将这些文件合成最终的gcov文件,命令如下
gcov hello.cpp
运行结束以后会生成存有具体覆盖率信息的文件hello.cpp.gcov。打开看里面的信息:
-: 0:Source:hello.cpp
-: 0:Graph:hello.gcno
-: 0:Data:hello.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include
-: 2:using namespace std;
-: 3:
1: 4:int main()
-: 5:{
1: 6: cout << "Hello, World!";
1: 7: return 0;
3: 8:}
添加以下参数可以看到更多覆盖率信息:
Usage: gcov [OPTION]... SOURCE|OBJ...
显示代码覆盖信息。
-h, --help 打印此帮助并退出
-v, --version 打印版本号并退出
-a, --all-blocks 显示每个基本块的信息
-b, --branch-probabilities 输出包含分支概率
-c, --branch-counts 给出跳转的分支数,而不是百分比
-n, --no-output 不创建输出文件
-l, --long-file-names 为包含进来的源文件使用长输出文件名
-f, --function-summaries 输出每个函数的小结信息
-o, --object-directory DIR|FILE 在 DIR 中搜索目标文件,或搜索名为 FILE 的目标文件
-s, --source-prefix DIR Source prefix to elide
-r, --relative-only Only show data for relative sources
-p, --preserve-paths 保留所有路径名
-u, --unconditional-branches 同时显示无条件跳转数
-d, --display-progress 显示进度信息
从1.2看到的代码覆盖的信息是正确的, 但是既不直观也不方便。lcov
可以用程序解析这些晦涩的字符, 最终输出成 html
格式的报告。
lcov
可以在指定目录去找代码覆盖的信息, 输出为 *.info
, 这个 *.info
是一个中间结果
lcov -c -o collector.info -d .
更多使用方法见:
Usage: lcov [OPTIONS]
Use lcov to collect coverage data from either the currently running Linux
kernel or from a user space application. Specify the --directory option to
get coverage data for a user space program.Misc:
-h, --help Print this help, then exit
-v, --version Print version number, then exit
-q, --quiet Do not print progress messagesOperation:
-z, --zerocounters Reset all execution counts to zero
-c, --capture Capture coverage data
-a, --add-tracefile FILE Add contents of tracefiles
-e, --extract FILE PATTERN Extract files matching PATTERN from FILE
-r, --remove FILE PATTERN Remove files matching PATTERN from FILE
-l, --list FILE List contents of tracefile FILE
--diff FILE DIFF Transform tracefile FILE according to DIFF
--summary FILE Show summary coverage data for tracefilesOptions:
-i, --initial Capture initial zero coverage data
-t, --test-name NAME Specify test name to be stored with data
-o, --output-file FILENAME Write data to FILENAME instead of stdout
-d, --directory DIR Use .da files in DIR instead of kernel
-f, --follow Follow links when searching .da files
-k, --kernel-directory KDIR Capture kernel coverage data only from KDIR
-b, --base-directory DIR Use DIR as base directory for relative paths
--convert-filenames Convert filenames when applying diff
--strip DEPTH Strip initial DEPTH directory levels in diff
--path PATH Strip PATH from tracefile when applying diff
--(no-)checksum Enable (disable) line checksumming
--(no-)compat-libtool Enable (disable) libtool compatibility mode
--gcov-tool TOOL Specify gcov tool location
--ignore-errors ERRORS Continue after ERRORS (gcov, source, graph)
--no-recursion Exclude subdirectories from processing
--to-package FILENAME Store unprocessed coverage data in FILENAME
--from-package FILENAME Capture from unprocessed data in FILENAME
--no-markers Ignore exclusion markers in source code
--derive-func-data Generate function data from line data
--list-full-path Print full path during a list operation
--(no-)external Include (ignore) data for external files
--config-file FILENAME Specify configuration file location
--rc SETTING=VALUE Override configuration file setting
--compat MODE=on|off|auto Set compat MODE (libtool, hammer, split_crc)
genhtml
也是 lcov
里面的一个工具,可以使用*.info 数据 生成html数据。
genhtml collector.info -o collector_result
更多使用方法见:
Usage: genhtml [OPTIONS] INFOFILE(S)
Create HTML output for coverage data found in INFOFILE. Note that INFOFILE
may also be a list of filenames.Misc:
-h, --help Print this help, then exit
-v, --version Print version number, then exit
-q, --quiet Do not print progress messages
--config-file FILENAME Specify configuration file location
--rc SETTING=VALUE Override configuration file setting
--ignore-errors ERRORS Continue after ERRORS (source)Operation:
-o, --output-directory OUTDIR Write HTML output to OUTDIR
-s, --show-details Generate detailed directory view
-d, --description-file DESCFILE Read test case descriptions from DESCFILE
-k, --keep-descriptions Do not remove unused test descriptions
-b, --baseline-file BASEFILE Use BASEFILE as baseline file
-p, --prefix PREFIX Remove PREFIX from all directory names
--no-prefix Do not remove prefix from directory names
--(no-)function-coverage Enable (disable) function coverage display
--(no-)branch-coverage Enable (disable) branch coverage displayHTML output:
-f, --frames Use HTML frames for source code view
-t, --title TITLE Display TITLE in header of all pages
-c, --css-file CSSFILE Use external style sheet file CSSFILE
--no-source Do not create source code view
--num-spaces NUM Replace tabs with NUM spaces in source view
--highlight Highlight lines with converted-only data
--legend Include color legend in HTML output
--html-prolog FILE Use FILE as HTML prolog for generated pages
--html-epilog FILE Use FILE as HTML epilog for generated pages
--html-extension EXT Use EXT as filename extension for pages
--html-gzip Use gzip to compress HTML
--(no-)sort Enable (disable) sorted coverage views
--demangle-cpp Demangle C++ function names
--precision NUM Set precision of coverage rate
有的时候,需要多次运行程序对应不同的测试情况,这种时候怎么将不同次的统计合并到一起形成一个统一的代码覆盖率呢?
可以使用lcov实现,每次使用lcov生成.Info文件后,可以是使用lcov -a参数合并.info文件:
Lcov -a a.info -a b.info -o all.info
然后使用all.info执行genhtml生成最终的代码覆盖率。
如不需要统计覆盖率信息,则需要屏蔽,或者只需要某些文件的覆盖率,就需要对文件进行筛选
lcov --remove all.info '/src/include/*' '/user/bin/*' -o result.info
此命令表示生成的覆盖率信息,屏蔽 '/src/include/*' '/user/bin/*' 两个目录的覆盖率信息
all.info 总的覆盖率信息
result.info 筛选后的覆盖率信息
lcov --extract all.info '*/src/*' '*/lib/*' -o result.info
此命令表示生成的覆盖率信息只要src和lib目录下文件的覆盖率信息
all.info 总的覆盖率信息
result.info 筛选后的覆盖率信息