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 build
cmake ..
命令行输入 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 4
Creating '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 5
Creating '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,用浏览器打开,如下: