ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

gtest测试框架

gtest测试框架

文章目录

  • 前言
  • 1 单元测试
  • 2 gtest安装
  • 3 gtest原理
  • 4 断言
    • 4.1 明确指定或失败
    • 4.2 布尔条件
    • 4.3 二元比较
    • 4.4 谓词断言
    • 4.5 死亡测试
  • 5 gtest使用
    • 5.1 测试函数
    • 5.2 测试类
    • 5.3 测试夹具
    • 5.4 类型参数化
    • 5.5 事件
  • 总结

前言

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 googletestcmake CMakeLists.txtmakesudo 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 = val2EXPECT_EQ( val1 , val2 )ASSERT_EQ( val1 , val2 )// val1 != val2,空指针使用 nullptrEXPECT_NE( val1 , val2 )ASSERT_NE( val1 , val2 )// val1 <= val2EXPECT_LT( val1 , val2 )ASSERT_LT( val1 , val2 )// val1 > val2EXPECT_GT( val1 , val2 )ASSERT_GT( val1 , val2 )// val1 >= val2EXPECT_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);}// 测试阶乘:0TEST(FactorialTest, Zero) { EXPECT_EQ(1, Factorial(0)); }// 测试阶乘:正数TEST(</
返回列表