gcov 是一个能统计代码覆盖率的工具,是 GCC 编译器的一部分,不需要单独下载安装,可以统计每一行代码是否执行、执行次数、执行时间,统计出 C/C++ 程序的语句覆盖和分支覆盖情况。
gcov 只在使用GCC编译的代码上工作。它与任何其他概要或测试覆盖机制不兼容。
1、在编译命令上添加编译选项 -fprofile-arcs -ftest-coverage
2、编译源程序
3、运行程序
4、使用 gcov 查看代码覆盖率
创建类 GcovTest,如下:
头文件 gcov_test.h :
#ifndef GCOV_TEST_H_#define GCOV_TEST_H_#include <string>class GcovTest {public:GcovTest();~GcovTest();public:void Print(const std::string& message);};#endif
源文件 gcov_test.cc :
#include "gcov_test.h"#include <stdio.h>GcovTest::GcovTest() {}GcovTest::~GcovTest() {}void GcovTest::Print(const std::string& message) {printf("%s", message.c_str());}
主程序 main.cc :
#include "gcov_test.h"int main(int argc, char** argv) {GcovTest gcov_test;gcov_test.Print("this is a gcov test message\n");}
CMakeLists.txt :
cmake_minimum_required(VERSION 3.5.1)project(gcov_test)set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")include_directories(gcov_test_SOURCE_DIR)add_executable(gcov_test main.cc gcov_test.cc)
在项目文件目录,创建 build 文件夹,并输入 cmake .. 命令编译:
cd buildcmake ..
命令行输入 find ./ -name "*.gcno",可以看到编译生成的以 .gcno 结尾的编译好的文件:
find ./ -name "*.gcno"// 输出结果./CMakeFiles/gcov_test.dir/main.cc.gcno./CMakeFiles/gcov_test.dir/gcov_test.cc.gcno
运行编译好的程序(要看到覆盖率等数据,需要运行程序才会生成):
./gcov_test
使用 gcov 命令生成覆盖率文件,并查看覆盖率结果:
gcov ./CMakeFiles/gcov_test.dir/main.cc.gcno// 输出结果File '/home/mobvoi/github/aitool/gcov/main.cc'Lines executed:100.00% of 4Creating 'main.cc.gcov'gcov ./CMakeFiles/gcov_test.dir/gcov_test.cc.gcno// 输出结果File '/home/mobvoi/github/aitool/gcov/gcov_test.cc'Lines executed:100.00% of 5Creating 'gcov_test.cc.gcov'
从上面输出可以看到main.cc和gcov_test.cc的覆盖率均为100%,要查看对应的源文件的覆盖率,使用cat main.cc.gcov即可:
cat main.cc.gcov// main.cc 文件的覆盖率统计:-: 0:Source:/home/mobvoi/github/aitool/gcov/main.cc-: 0:Graph:./CMakeFiles/gcov_test.dir/main.cc.gcno-: 0:Data:./CMakeFiles/gcov_test.dir/main.cc.gcda-: 0:Runs:2-: 0:Programs:1-: 1:#include "gcov_test.h"-: 2:2: 3:int main(int argc, char** argv) {4: 4: GcovTest gcov_test;2: 5: gcov_test.Print("this is a gcov test message\n");2: 6:}cat gcov_test.cc.gcov// gcov_test.cc 文件的覆盖率统计:-: 0:Source:/home/mobvoi/github/aitool/gcov/gcov_test.cc-: 0:Graph:./CMakeFiles/gcov_test.dir/gcov_test.cc.gcno-: 0:Data:./CMakeFiles/gcov_test.dir/gcov_test.cc.gcda-: 0:Runs:2-: 0:Programs:1-: 1:#include "gcov_test.h"-: 2:-: 3:#include <stdio.h>-: 4:2: 5:GcovTest::GcovTest() {}-: 6:2: 7:GcovTest::~GcovTest() {}-: 8:2: 9:void GcovTest::Print(const std::string& message) {2: 10: printf("%s", message.c_str());2: 11:}-: 12:
上面结果中 “-“ 表示此行无意义,不进行统计(如注释、括号行、空行等),冒号前面的数字表示此行共运行次数,如果没有被运行到,将会显示为 “#####”
首先需要安装 lcov 工具:
sudo apt-get install lcov
生成可视化页面:
# 初始化 lcov,收集所有生成的覆盖率文件,-c 捕获,-i 初始化,-d 应用目录,-o 输出文件名称lcov -c -d ./ -o cover.info# 合并覆盖率文件,-a 合并文件lcov -a cover.info -o total.info# 移除不需要关注的文件目录,如标准库文件lcov --remove total.info '*/usr/include/*' '*/usr/lib/*' '*/usr/lib64/*' '*/usr/local/include/*' '*/usr/local/lib/*' '*/usr/local/lib64/*' -o final.info# 生成 html 文件# 获取 git 的commit id# commit_id=$(git log | head -n1 | awk '{print $2}')# 加上项目名称和commit id# genhtml -o cover_report --legend --title "${project_name} commit SHA1:${commit_id}" --prefix=./ final.info# -o 生成的html及相关文件的目录名称,--legend 简单的统计信息说明# --title 项目名称,--prefix 将要生成的html文件的路径genhtml -o cover_report --legend --title "lcov" --prefix=./ final.info
可以看到 cover_report 下生成了index.html,用浏览器打开,如下: