【Linux】使用GTest和CuTest编写测试用例,使用GCOV和LCOV测试代码覆盖率
文章目录
单元测试
一、Google Test
Google Test(简称GTest) 是一个用于 C++ 编程语言的单元测试框架。它是由 Google 开发并开源的一个项目,旨在帮助开发者编写高质量的 C++ 代码。使用 Google Test,开发者可以轻松地为他们的 C++ 应用程序创建测试用例,确保代码的正确性和稳定性。
主要特点
- 支持多种平台和编译器:Google Test 支持 Windows、Linux、MacOS 等多个平台和多种编译器,包括 GCC、Clang、MSVC 等
- 丰富的断言:提供了一系列的断言宏来检查代码的正确性,例如
EXPECT_EQ用于比较两个值是否相等。 - 测试固定装置:允许定义一个测试环境(称为测试固定装置),在多个测试中重用这个环境,以减少重复代码。
- 死亡测试:可以用来验证某些代码是否会如预期那样导致程序崩溃。
- 性能测试:支持编写性能测试用例,可以测量代码的执行时间。
- 易于集成:可以与各种构建系统(如 CMake、Bazel)和持续集成服务(如 Jenkins)集成。
使用步骤
- 下载 Google Test:可以从 Google Test的官方网站或 GitHub 仓库下载源代码。
- 编译 Google Test:将 Google Test源代码编译成静态库或直接包含源文件到你的项目中。
- 编写测试用例:使用 Google Test提供的宏和函数来定义测试用例。
- 运行测试:编译并运行包含测试用例的程序,查看测试结果。
示例代码
文件结构
root@z-VirtualBox:/disk3/gTest# tree
.
├── calculate_gtest.cc #测试用例,使用gTest测试函数功能
├── calculate.c #定义函数
├── calculate.h #声明函数
├── gtest #编译好的GTest
│ ├── include
│ └── lib
│ ├── libgtest.a
│ └── libgtest_main.a
└── libcalculate.so #使用g++编译出的动态库
待测试的代码: calculate.h、calcualte.c
//calculate.h
#ifndef __CALCULATE_H__
#define __CALCULATE_H__
#include <stdio.h>
#include <stdlib.h>
int add(int a, int b);
int sub(int a, int b);
int divide(int a,int b);
#endif
//calcualte.c
#include "calculate.h"
int add(int a,int b){
return a+b;
}
int sub(int a, int b){
return a-b;
}
测试用例: calcualte_gtest.cc
//calcualte_gtest.cc
#include "calculate.h"
#include <gtest/gtest.h>
TEST(calculateTest,addTest)
{
EXPECT_EQ(88,add(80,8));
EXPECT_EQ(0,add(1,-1));
}
TEST(calculateTest,subTest)
{
EXPECT_EQ(8,sub(10,2));
EXPECT_EQ(2,sub(1,-1));
}
编译测试用例
1、不使用libcalculate.so
g++ calculate.c calculate_gtest.cc -o a.out -I. -Igtest/include -Lgtest/lib -lgtest -lgtest_main -lpthread
2、使用libcalculate.so
1)编译出ibcalculate.so
g++ -shared -fPIC -I ./ -o ./libcalculate.so calculate.c
2)链接到libcalculate.so
g++ calculate_gtest.cc -o a.out -I. -Igtest/include -Lgtest/lib -lgtest -lgtest_main -L. -lcalculate -lpthread
静态库、动态库的相关文章:C/C++静态库和动态库(共享库)
3.运行a.out

Google Test相关学习资料(学习如何编译得到GTest库,以及GTest的使用):
玩转Google开源C++单元测试框架Google Test系列
感谢以上文章的作者。
二、CuTest
CuTest 是一个轻量级的 C 语言单元测试框架。它由 Neil Butterworth 开发,设计目的是为了简单易用,同时保持足够的功能来满足大多数 C 语言项目的测试需求。CuTest 的主要特点是其简洁性和易用性,使得开发者可以快速上手并开始编写测试用例。
主要特点
- 简单易用:API 非常简单,容易学习和使用。
- 轻量级:库文件非常小,不会给项目带来额外的负担。
- 跨平台:可以在多种操作系统上运行,包括 Windows、Linux 和 macOS。
- 文本输出:测试结果以文本形式输出,便于阅读和调试。
使用步骤
- 下载 CuTest:可以从 CuTest 的官方网站或 GitHub 仓库下载源代码。
- 编译 CuTest:将 CuTest 源代码编译成静态库或直接包含源文件到你的项目中。
- 编写测试用例:使用 CuTest 提供的宏和函数来定义测试用例。
- 运行测试:编译并运行包含测试用例的程序,查看测试结果。
示例代码
文件结构
root@z-VirtualBox:/disk3/cuTest# tree
.
├── calculate_cuTest.c #使用cuTest编写测试用例
├── calculate.c #同上
├── calculate.h #同上
├── cutest
│ ├── include
│ │ └── CuTest.h
│ └── lib
│ └── libcutest.a
└── libcalculate.so #使用gcc编译
测试用例:calculate_cuTest.c
//calculate_cuTest.c
/* 包含cutest头文件 */
#include "CuTest.h"
#include "calculate.h"
/**
* @note
* 定义测试用例xxx
*/
static void CuTestCase_0(CuTest *tc)
{
/// 断言测试
CuAssertIntEquals(tc, 2, add(1, 1));
}
static void CuTestCase_1(CuTest *tc)
{
/// 断言测试
CuAssertIntEquals(tc, 1 , sub(2,1));
}
/**
* @note
* 定义测试套件
*/
static CuSuite *CuSuite_x(void)
{
CuSuite *suite = CuSuiteNew();
/// 将测试用例添加到测试套件中
SUITE_ADD_TEST(suite, CuTestCase_0);
SUITE_ADD_TEST(suite, CuTestCase_1);
return suite;
}
static void RunAllTests(void)
{
CuSuite *suite = CuSuiteNew();
CuString *output = CuStringNew();
/// 声明测试套件,并增加测试用例
CuSuiteAddSuite(suite, CuSuite_x());
/// 运行所有测试用例
CuSuiteRun(suite);
/// 输出测试结果
CuSuiteSummary(suite, output);
CuSuiteDetails(suite, output);
printf("\n\033[36m-----------------------------------------------------------------------------\n");
printf("[%s] Test Result:\n", __FILE__);
printf("%s\n", output->buffer);
printf("\n[%s] End of Test Result.\n", __FILE__);
printf("-----------------------------------------------------------------------------\033[0m\n\n");
/// 释放测试资源
CuStringDelete(output);
CuSuiteDelete(suite);
}
int main(int argc, char *argv[])
{
RunAllTests();
return 0;
}
编译测试用例
1、不使用libcalculate.so
gcc calculate.c calculate_cuTest.c -o a.out -I. -Icutest/include -Lcutest/lib -lcutest -lpthread
2、使用libcalculate.so
1)编译出libcalculate.so
gcc -shared -fPIC -I ./ -o ./libcalculate.so calculate.c
2)链接到libcalculate.so
gcc calcualte_cuTest.c -o a.out -I. -Icutest/include -Lcutest/lib -lcutest -L. -lcalculate -lpthread
3.运行a.out

代码覆盖率测试
代码覆盖率测试是一种评估软件测试质量的方法,通过测量测试用例执行时实际覆盖到的源代码的比例,来判断测试的充分性。高覆盖率通常意味着更多的代码路径得到了验证,从而提高了软件的可靠性和质量。常用的覆盖率指标包括:
- 行覆盖率(Line Coverage):已执行的代码行数占总代码行数的比例。
- 分支覆盖率(Branch Coverage):已执行的条件分支数占总条件分支数的比例。
- 函数覆盖率(Function Coverage):已调用的函数数占总函数数的比例。
- 语句覆盖率(Statement Coverage):已执行的语句数占总语句数的比例。
- 路径覆盖率(Path Coverage):已执行的路径数占总路径数的比例。
有许多工具可以帮助进行代码覆盖率测试,下面只介绍gcov和lcov
gcov:GNU Compiler Collection 提供的覆盖率测试工具,适用于 C 和 C++ 代码。
lcov:基于 gcov 的图形化前端,可以生成 HTML 报告。
GCOV的工作原理:编译器编译源代码时,将额外的代码注入到目标代码中,这些代码将用于记录每个源代码行被执行的次数。当程序运行时,gcov会生成一个.gcda文件,其中包含记录了代码执行信息的数据。然后,通过运行gcov命令来解析这个文件,并将其与源代码相匹配,生成一个HTML格式的测试报告,显示了每个源代码行被执行的次数、未被执行的代码行以及总体覆盖率等信息。
一、使用 gcov 和 lcov 进行代码覆盖率测试
安装工具
首先,确保你已经安装了 gcov 和 lcov。在大多数 Linux 发行版中,可以通过包管理器安装:
sudo apt-get install gcov lcov
编译代码
-g选项是为了生成调试信息,-fprofile-arcs选项是为了生成代码覆盖率统计信息
gcc -g -fprofile-arcs -ftest-coverage test.c -o test
这将生成一个名为test的可执行文件和一个名为test.gcno的文件
运行程序
./test
运行完程序后,在程序所在目录下会生成一个名为test.gcda的文件,这个文件记录了程序运行时每个代码块被执行的次数
生成覆盖率报告
使用 lcov 生成覆盖率数据文件,并生成 HTML 报告。
# 生成行覆盖率
lcov --capture --directory . --output-file test.info
# 生成分支覆盖率
lcov --capture --directory . --output-file test.info --rc lcov_branch_coverage=1
将在当前目录下生成一个名为test.info的文件,其中包含了测试覆盖率的数据。接着运行genhtml命令,生成HTML格式的测试覆盖率报告
genhtml test.info --output-directory out
这将生成一个名为out的目录,其中包含了各种统计信息和测试覆盖率报告。
查看报告
打开生成的index.html文件,查看测试覆盖率和未被覆盖到的代码行等信息
tip:通过以上步骤我们可以发现:lcov需要在gcov生成的数据文件的基础上进行操作,因此在使用lcov之前必须先运行测试用例并生成gcov数据文件。另外,lcov还支持一些高级的功能,例如过滤不需要统计的文件和代码行等,可以根据实际需要进行配置。
更多推荐
所有评论(0)