如何使用GoogleTest和CTest进行单元测试
如何使用GoogleTest和CTest进行单元测试
对于大多数网友来说如何使用GoogleTest和CTest进行单元测试方面的内容,接下来IT袋网带大家一起了解。
本文我将介绍如何通过GoogleTest和CTest将单元测试集成到这个构建系统中。
首先克隆 这个仓库,用 VSCodium 打开,切换到devops_2标签。
你可以通过点击main分支符号(红框处),然后选择devops_2标签(黄框处)来进行切换:

或者你可以通过命令行来切换:
$ git checkout tags/devops_2
GoogleTest
GoogleTest 是一个平台无关的开源 C++ 测试框架。单元测试是用来验证单个逻辑单元的行为的。尽管 GoogleTest 并不是专门用于单元测试的,我将用它对Generator库进行单元测试。
在 GoogleTest 中,测试用例是通过断言宏来定义的。断言可能产生以下结果:
- 成功: 测试通过。
- 非致命失败: 测试失败,但测试继续。
- 致命失败: 测试失败,且测试终止。
致命断言和非致命断言通过不同的宏来区分:
ASSERT_*: 致命断言,失败时终止。EXPECT_*: 非致命断言,失败时不终止。
谷歌推荐使用EXPECT_*宏,因为当测试中包含多个的断言时,它允许继续执行。断言有两个参数:第一个参数是测试分组的名称,第二个参数是测试自己的名称。Generator只定义了generate(...)函数,所以本文中所有的测试都属于同一个测试组:GeneratorTest。
针对generate(...)函数的测试可以从GeneratorTest.cpp中找到。
引用一致性检查
generate(…)函数有一个std::stringstream的引用作为输入参数,并且它也将这个引用作为返回值。第一个测试就是检查输入的引用和返回的引用是否一致。
TEST(GeneratorTest, ReferenceCheck){
const int NumberOfElements = 10;
std::stringstream buffer;
EXPECT_EQ(
std::addressof(buffer),
std::addressof(Generator::generate(buffer, NumberOfElements))
);
}
在这个测试中我使用 std::addressof来获取对象的地址,并用EXPECT_EQ来比较输入对象和返回对象是否是同一个。
检查元素个数
本测试检查作为输入的std::stringstream引用中的元素个数与输入参数中指定的个数是否相同。
TEST(GeneratorTest, NumberOfElements){
const int NumberOfElements = 50;
int nCalcNoElements = 0;
std::stringstream buffer;
Generator::generate(buffer, NumberOfElements);
std::string s_no;
while(std::getline(buffer, s_no, ' ')) {
nCalcNoElements++;
}
EXPECT_EQ(nCalcNoElements, NumberOfElements);
}
乱序重排
本测试检查随机化引擎是否工作正常。如果连续调用两次generate函数,应该得到的是两个不同的结果。
TEST(GeneratorTest, Shuffle){
const int NumberOfElements = 50;
std::stringstream buffer_A;
std::stringstream buffer_B;
Generator::generate(buffer_A, NumberOfElements);
Generator::generate(buffer_B, NumberOfElements);
EXPECT_NE(buffer_A.str, buffer_B.str);
}
求和校验
与前面的测试相比,这是一个大体量的测试。它检查 1 到 n 的数值序列的和与乱序重排后的序列的和是否相等。generate(...)函数应该生成一个 1 到 n 的乱序的序列,这个序列的和应当是不变的。
TEST(GeneratorTest, CheckSum){
const int NumberOfElements = 50;
int nChecksum_in = 0;
int nChecksum_out = 0;
std::vector
你可以像对一般 C++ 程序一样调试这些测试。
CTest
除了嵌入到代码中的测试之外,CTest提供了可执行程序的测试方式。简而言之就是通过给可执行程序传入特定的参数,然后用正则表达式对它的输出进行匹配检查。通过这种方式可以很容易检查程序对于不正确的命令行参数的反应。这些测试定义在顶层的CMakeLists.txt文件中。下面我详细介绍 3 个测试用例:
参数正常
如果输入参数是一个正整数,程序应该输出应该是一个数列:
add_test(NAME RegularUsage COMMAND Producer 10)
set_tests_properties(RegularUsage
PROPERTIES PASS_REGULAR_EXPRESSION "^[0-9 ]+"
)
没有提供参数
如果没有传入参数,程序应该立即退出并提示错误原因:
add_test(NAME NoArg COMMAND Producer)
set_tests_properties(NoArg
PROPERTIES PASS_REGULAR_EXPRESSION "^Enter the number of elements as argument"
)
参数错误
当传入的参数不是整数时,程序应该退出并报错。比如给Producer传入参数ABC:
add_test(NAME WrongArg COMMAND Producer ABC)
set_tests_properties(WrongArg
PROPERTIES PASS_REGULAR_EXPRESSION "^Error: Cannot parse"
)
执行测试
可以使用ctest -R Usage -VV命令来执行测试。这里给ctest的命令行参数:
-R: 执行单个测试-VV:打印详细输出
测试执行结果如下:
$ ctest -R Usage -VV
UpdatecTest Configuration from :/home/stephan/Documents/cpp_testing sample/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/stephan/Documents/cpp_testing sample/build/DartConfiguration.tcl
Test project /home/stephan/Documents/cpp_testing sample/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
在这里我执行了名为Usage的测试。
它以无参数的方式调用Producer:
test 3
Start 3: Usage
3: Test command: /home/stephan/Documents/cpp testing sample/build/Producer
输出不匹配[^[0-9]+]的正则模式,测试未通过。
3: Enter the number of elements as argument
1/1 test #3. Usage ................
Failed Required regular expression not found.
Regex=[^[0-9]+]
0.00 sec round.
0% tests passed, 1 tests failed out of 1
Total Test time (real) =
0.00 sec
The following tests FAILED:
3 - Usage (Failed)
Errors while running CTest
$
如果想要执行所有测试(包括那些用 GoogleTest 生成的),切换到build目录中,然后运行ctest即可:

在 VSCodium 中可以通过点击信息栏的黄框处来调用 CTest。如果所有测试都通过了,你会看到如下输出:

使用 Git 钩子进行自动化测试
目前为止,运行测试是开发者需要额外执行的步骤,那些不能通过测试的代码仍然可能被提交和推送到代码仓库中。利用 Git 钩子可以自动执行测试,从而防止有瑕疵的代码被提交。
切换到.git/hooks目录,创建pre-commit文件,复制粘贴下面的代码:
#!/usr/bin/sh
(cd build; ctest --output-on-failure -j6)
然后,给文件增加可执行权限:
$ chmod +x pre-commit
这个脚本会在提交之前调用 CTest 进行测试。如果有测试未通过,提交过程就会被终止:
相关阅读
-
access数据库有什么用处 新手access数据库入门教程
为大家说一说access数据库有什么用处和新手access数据库入门教程的相关知识,一起来了解了解吧。 第1课我讲了Access数据库的作用和基本界面,本讲书接上回,我来讲一讲Access数据库的五大组件
-
网站架构是什么意思 分析一个网站的架构
小编为网友们解答网站架构是什么意思和分析一个网站的架构方面的介绍,继续往下看吧! 导读: 理解架构这个词的意思是十分重要的。它可能被过度使用,并且使用在各种环境中。如果缺少
-
lol查别人战绩的网站叫什么 lol公众号查隐藏战绩教学
一篇很详细的教程是关于lol查别人战绩的网站叫什么和lol公众号查隐藏战绩教学的相关介绍,下面来一起了解一下吧。 lol战绩查询网页版地址入口 :对于英雄联盟游戏战绩查询还是非常有必要
-
网页登录界面设计 自己创建一个网站的教程
一个电脑小知识,为大家介绍网页登录界面设计和自己创建一个网站的教程的相关经验,接下来小编为网友介绍。 登录页面设计是网站用户体验流程的关键部分。好的设计有助于推动访问者访


