最近在统计C++项目代码的单元测试覆盖率
发现通过gcov和lcov就能将代码单元测试覆盖率定量化和可视化
下面是基于gtest测试框架,对gcov和lcov生成覆盖率的简单示例
工作流程
主要有三个步骤
-
向GCC编译添加特殊的编译选项以生成可执行文件和*.gcno
-
运行(测试)生成的可执行文件,生成*.gcda数据文件
-
使用*.gcno和*.gcda,从源代码生成gcov文件,最后生成代码覆盖率报告
效果展示
行覆盖率和函数覆盖率统计
统计到具体文件
简单实践
1. 安装gtest和lcov
# 1 安装gtest(也可以自己编译)
apt-get install libgtest-dev
# 2 gcov工具属于gcc内置,无需单独安装
# 3 安装lcov工具,数据格式转换
sudo apt install lcov
2. 编写一个程序
首先,编写一个简单的程序,实现功能为:求三个数字中最大的一个
main.cpp
#include<iostream>
using namespace std;
int GreatestOfThree(int a,int b,int c){
if((a>b) && (a>c)){ //for a > b and a>c case
return a;
}
else if(b>c){ //for b>c case
return b;
}
else{
return c;
}
return 0;
}//After checking for correctness comment main function to test //main_test.cpp
int main()
{
// your code goes here
int a,b,c;
cin>>a>>b>>c;
cout<<GreatestOfThree(a,b,c);
return 0;
}
然后编译程序
g++ -o main main.cpp
验证测试程序正常工作
$./main 1 2 3
$ 3
程序输出了三个数中的最大一个
3. 编写测试用例
使用gtest编写测试用例
main_test.cpp
#include "gtest/gtest.h"
#include "main.cpp"
TEST(GreaterTest,AisGreater){
EXPECT_EQ(3,GreatestOfThree(3,1,2));};
TEST(GreaterTest,BisGreater){
EXPECT_EQ(3,GreatestOfThree(1,3,2));};
TEST(GreaterTest,CisGreater){
EXPECT_EQ(3,GreatestOfThree(1,2,3));};
int main(int argc,char**argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
这里我们为了简单起见,没有写头文件,直接将功能源文件包含进了测试用例文件中
4. 编译并执行
编译并生成一个可执行文件main
g++ -o main main_test.cpp
执行测试用例
./main
[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from GreaterTest
[ RUN ] GreaterTest.AisGreater
[ OK ] GreaterTest.AisGreater (0 ms)
[ RUN ] GreaterTest.BisGreater
[ OK ] GreaterTest.BisGreater (0 ms)
[ RUN ] GreaterTest.CisGreater
[ OK ] GreaterTest.CisGreater (0 ms)
[----------] 3 tests from GreaterTest (0 ms total)[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (0 ms total)
[ PASSED ] 3 tests.
5. 生成代码覆盖率报告
这一步会使用gcov工具,这个工具一般gcc都自带了,无需安装
5.1 生成启用覆盖率的可执行文件
g++ -o main -fprofile-arcs -ftest-coverage main_test.cpp
5.2 运行并生成报告所需文件
./main
这一步会生成两种类型的文件(用于创建覆盖率报告)
-
.gcno结尾,包含基本构造和行号信息,在g++编译时添加了-ftest覆盖率标志后生成
-
.gcda结尾,包含评测和覆盖率信息,这些信息是由g++命令中的-fprofile arcs标志而生成。
5.3 通过gcov生成报告
gcov main_test.cpp
这一步生成了main_test.cpp.gcov命名的报告,但是这个报告不好阅读
5.4 生成html版本的报告
首先,使用lcov生成行覆盖率报告
lcov --coverage --directory . --output-file main_coverage.info
lcov自动读取当前目录下的.gcno和.gcda文件创建覆盖率报告,并将生成具有覆盖率信息的输出到文件main_coverage.info
然后,将覆盖率报告转换成html格式
genhtml main_coverage.info --output-directory out
在out目录下生成html格式的报告
5.5 最后,查看报告
在浏览器中打开报告目录下的index.html文件检查覆盖率,主要是行覆盖率和函数覆盖率
至此,我们就获取到了源文件的测试覆盖率数据
一起学习,一起进步