gtest测试框架

前言

GoogleTest(GTest) 是谷歌开源的 C++ 单元测试框架。

1 单元测试

单元测试unit testing是指对软件中的最小可测试单元进行检查和验证,包括函数、类、模块、复杂交互逻辑等。gtest 中单元测试以单例模式实现。每个单元测试包含若干个测试套件test suite,测试套件是指一组功能相同的测试脚本或过程。每个测试套件包含多个测试案例test case,测试同一个功能的不同方向。
在这里插入图片描述
根据 gtest 官方文档,一个好的单元测试应该满足:

  • 独立、可重复:测试案例可单独执行,错误可重复发生。
  • 反映测试代码结构:功能完整,体现完备逻辑。对于关联功能,一个功能是否影响其他功能
  • 可移植、可复用:跨平台。
  • 尽可能多的出错信息:不会因为一次失败而停止,会继续测试下一个测试案例。一次测试发现多个错误。
  • 自动跟踪所有测试而无需枚举:向容器中添加
  • 测试高效:测试间重用资源,mock 模拟复杂交互

如何整体使用单元测试?

  • 每个类或功能块加上测试案例
  • test 目录加上所有的测试
  • 一个单元测试可能散落在多个文件

单元测试中的打桩,是指用来代替关联代码或者未实现代码的代码,即用桩函数代替原函数。打桩测试由 gtest 里的 gmock 来实现。

2 gtest安装

 # 下载
 git clone https://github.com/google/googletest.git
 # 安装
 cd googletest
 cmake CMakeLists.txt
 make
 sudo make install

源码文件中的 lib 库,包含 gtest 库和 gmock 库。

 libgtest.a  libgtest_main.a  libgmock.a  libgmock_main.a

当测试代码有 main 函数,使用不带 main 的静态库,否则使用带 main 的静态库。

 # 无 main 函数
 g++ sample.cc sample_unittest.cc -o sample -lgtest -lgtest_main -lpthread
 # 有 main 函数
 g++ gmock_output_test_.cc -o output -lgtest -lgmock -lpthread

若需要编写 main 函数,关键在于添加两个地方

 int main(int argc, char **argv) {
   
   // 1.定义 main 函数:初始化 gtest
   ::testing::InitGoogleTest(&argc, argv);
   // 2.定义 main 函数:开启全部测试
   return RUN_ALL_TESTS();
 }

3 gtest原理

GTest 测试底层原理

  • 创建单元测试类,单例模式实现,包含vector<TestSuite*>
  • 根据测试套件名,生成一个TestSuite 类实例,包含vector<TestInfo*>;
  • 根据测试案例名,生成一个Test_info类实例,继承父类 testing::Test
  • 将测试案例实例注册到测试套件中vector<TestSuite*>,测试套件类实例调用run方法执行测试

类的组织层次

 // 单元测试,单例模式实现
 class Impl {
   
     // 存储测试套件类实例
     vector<TestSuite*>;
 }// 测试套件
 class TestSuite {
   
     // 存储测试案例类实例
     vector<TestInfo*>;
     // 执行测试套件中的测试案例
     run();
 }// 测试案例
 class TestInfo {
   
     // 执行测试
     TestBody();
 };

4 断言

使用测试断言,通过断言其行为来测试类和函数。ASSERT_* 失败时会生成致命错误,并中止当前功能(但是他会执行测试套件中的下一个测试案例);EXPECT_失败时生成非致命错误,不会中止当前功能。通常选用EXPECT_

所有断言宏都支持输出流,经流输出的信息自动转换为utf-8,可利用这一特性输出详细错误信息

// 流后面可以使用中文,因为经流输出的信息会自动转换为utf-8
EXPECT_TRUE(my_condition) << "My condition is not true";

4.1 明确指定或失败

当测试案例中的条件太复杂,不能使用断言,那么自己写判断语句;自己返回成功或者失败;比如下面
在这里插入图片描述

4.2 布尔条件

 EXPECT_TRUE(condition)
 ASSERT_TRUE(condition)EXPECT_FALSE(condition)
 ASSERT_FALSE(condition)

4.3 二元比较

 // val1 = val2
 EXPECT_EQ( val1 , val2 )
 ASSERT_EQ( val1 , val2 )// val1 != val2,空指针使用 nullptr
 EXPECT_NE( val1 , val2 )
 ASSERT_NE( val1 , val2 )// val1 <= val2
 EXPECT_LT( val1 , val2 )
 ASSERT_LT( val1 , val2 )// val1 > val2
 EXPECT_GT( val1 , val2 )
 ASSERT_GT( val1 , val2 )// val1 >= val2
 EXPECT_GE( val1 , val2 )
 ASSERT_GE( val1 , val2 )

4.4 谓词断言

 EXPECT_PREDn( pred , val1, ..., valn ) \
 ASSERT_PREDn( pred , val1, ..., valn ) \

例如:测试阶乘函数,参数 1 个

EXPECT_PRED1(Factorial, 1)

说明:

  1. 谓词断言时,出错时会将参数打印出来,方便查看

4.5 死亡测试

用于测试程序是否以预期的方式崩溃。

EXPECT_DEATH(func, desc);

说明:

  1. 如果我们写了死亡测试用例,那么调用者读文档时,一看调用相关的参数会崩溃,这将会引起调用者的注意,从而使得它会做一些判断

5 gtest使用

5.1 测试函数

使用 TEST宏来定义测试案例。

 #include "sample1.h"
 #include <limits.h>
 #include "gtest/gtest.h"// 使用 TEST 宏定义测试案例 
 // #define TEST(test_suite_name,test_name)
 // 测试阶乘:负数
 TEST(FactorialTest, Negative) {
   
   // 断言:预期相等 EXPECT_EQ(expected, actual),后面同理
   EXPECT_EQ(1, Factorial(-5));
   EXPECT_EQ(1, Factorial(-1));
   EXPECT_GT(Factorial(-10), 0);
 }// 测试阶乘:0
 TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0)); }// 测试阶乘:正数
 TEST(FactorialTest, Positive) {
   
   EXPECT_EQ(1, Factorial(1));
   EXPECT_EQ(2, Factorial(2));
   EXPECT_EQ
  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用gtest测试框架实现快速排序的示例代码: ```c++ #include <gtest/gtest.h> void quickSort(int arr[], int left, int right) { int i = left, j = right; int tmp; int pivot = arr[(left + right) / 2]; // partition while (i <= j) { while (arr[i] < pivot) i++; while (arr[j] > pivot) j--; if (i <= j) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; i++; j--; } }; // recursion if (left < j) quickSort(arr, left, j); if (i < right) quickSort(arr, i, right); } TEST(QuickSortTest, PositiveNos) { int arr[] = { 5, 2, 3, 1, 4 }; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); ASSERT_EQ(arr[0], 1); ASSERT_EQ(arr[1], 2); ASSERT_EQ(arr[2], 3); ASSERT_EQ(arr[3], 4); ASSERT_EQ(arr[4], 5); } TEST(QuickSortTest, NegativeNos) { int arr[] = { -5, -2, -3, -1, -4 }; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); ASSERT_EQ(arr[0], -5); ASSERT_EQ(arr[1], -4); ASSERT_EQ(arr[2], -3); ASSERT_EQ(arr[3], -2); ASSERT_EQ(arr[4], -1); } TEST(QuickSortTest, MixedNos) { int arr[] = { -5, 2, -3, 1, 0 }; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); ASSERT_EQ(arr[0], -5); ASSERT_EQ(arr[1], -3); ASSERT_EQ(arr[2], 0); ASSERT_EQ(arr[3], 1); ASSERT_EQ(arr[4], 2); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ``` 在这个示例代码中,我们使用了gtest测试框架测试快速排序函数quickSort。我们定义了三个测试用例,分别测试了正数、负数和混合数的情况。在每个测试用例中,我们使用ASSERT_EQ宏来断言排序后数组的每个元素是否与预期值相等。如果不相等,则测试失败。 注意,这里的示例代码仅供参考,实际实现中可能需要根据具体情况进行相应修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值