本系列文章主要介绍 GoogleTest(也称“GTest”)测试框架的相关知识,同时通过一些示例程序介绍 GoogleTest 测试框架的使用方法。

本文为系列文章的第二篇,主要通过一些示例程序介绍 GoogleTest 测试框架的使用方法。

1 TEST()宏

TEST() 宏的第一个参数是 Test Case 的名称,第二个参数是(隶属于第一个 Test Case 参数的)Test 的名称。一个测试的完整名称包括 Test Case 名称及 Test 的名称,不同 Test CaseTest 名称可以相同。

GoogleTest 根据 Test Case 对测试结果进行分组,所以一些相关的 test 应当放入同一个 Test Case 中。

使用 TEST() 宏来编写一个测试程序,示例代码(gtest_test1.cpp)的内容如下:

#include "gtest/gtest.h"// 此函数用于判断入参是否为正整数:如果是,则返回0;否则,返回-1
int Positive(int nNum)
{if (nNum > 0){return 0;}else{return -1;}
}// 测试入参2是否为正整数
TEST(PositiveTest, HandlesPositiveInput)
{EXPECT_EQ(Positive(2), 0);
}// 测试入参0是否为正整数
TEST(PositiveTest, HandlesZeroInput)
{EXPECT_EQ(Positive(0), -1);
}// 测试入参-2是否为正整数
TEST(PositiveTest, HandlesNegativeInput)
{EXPECT_EQ(Positive(-2), -1);
}int main(int argc, char **argv)
{// 分析gtest程序的命令行参数testing::InitGoogleTest(&argc, argv);// 调用RUN_ALL_TESTS()运行所有测试用例// main函数返回RUN_ALL_TESTS()的运行结果return RUN_ALL_TESTS();
}

在上述代码中,我们编写了三个 test,分别为:HandlesPositiveInput、HandlesZeroInput 和 HandlesNegativeInput,这三个 test 都属于同一个 Test Case(PositiveTest)。

编译并执行上述代码,结果如下:

2 TEST_F()宏

当我们想让多个 test 使用同一套数据配置时,就需要用到 Test Fixtures 了。

Test Fixtures 的用法相对复杂一些,创建 fixture 的具体方法如下:

  1. 派生一个继承 ::testing::Test 的类,并将该类中的一些内容声明为 protected 类型,以便在子类中进行访问;
  2. 根据实际情况,编写默认的构造函数或SetUp()函数,来为每个 test 准备所需内容;
  3. 根据实际情况,编写默认的析构函数或TearDown()函数,来释放SetUp()中分配的资源;
  4. 根据实际情况,定义 test 共享的子程序。

当使用 fixture 时,我们使用 TEST_F() 宏代替 TEST() 宏,TEST_F() 允许我们在 Test Fixture 中访问对象和子程序。

注意:TEST_F() 的第一个参数(即 Test Case 的名称)必须是 Test Fixture 类的名字。

对于 TEST_F() 定义的每个 test,GoogleTest 将会在运行时创建一个新的 Test Fixture,并立即通过 SetUp() 对其进行初始化,然后运行 test,之后通过调用 TearDown() 进行数据清理,最后删除 Test Fixture。需要注意的是,同一个 Test Case 中不同的 test 具有不同的 Test Fixture 对象,并且 GoogleTest 每次创建新的 Test Fixture 前都会先删除之前的 Test Fixture。多个 test 不会重用相同的 Test Fixture,某个 test 对 fixture 进行的修改对其他 test 无影响。

使用 TEST_F() 宏来编写一个测试程序,示例代码(gtest_test2.cpp)的内容如下:

#include "gtest/gtest.h"// 定义测试类FooTest
class FooTest: public testing::Test {
protected:// Code here will be called immediately after the constructor (right before each test)void SetUp(){m_nTarget = 5;}// Code here will be called immediately after each test (right before the destructor)void TearDown(){}public:int IsLargeThan5(const int & nNum);int m_nTarget;
};// 判断入参是否大于5:如果是,则返回0;否则返回-1
int FooTest::IsLargeThan5(const int & nNum)
{if (nNum > m_nTarget){return 0;}else{return -1;}
}TEST_F(FooTest, HandlesInput6)
{EXPECT_EQ(IsLargeThan5(6), 0);
}TEST_F(FooTest, HandlesInput5)
{EXPECT_EQ(IsLargeThan5(5), 0);
}TEST_F(FooTest, HandlesInput4)
{EXPECT_EQ(IsLargeThan5(4), -1);
}int main(int argc, char **argv)
{// 分析gtest程序的命令行参数::testing::InitGoogleTest(&argc, argv);// 调用RUN_ALL_TESTS()运行所有测试用例// main函数返回RUN_ALL_TESTS()的运行结果return RUN_ALL_TESTS();
}

在上述代码中,我们编写了三个 test,分别为:HandlesInput6、HandlesInput5 和 HandlesInput4,这三个 test 都属于同一个 Test Case(即 FooTest)。注意,这里的 Test Case(即 FooTest) 一定要是 Test Fixture 类。

上述代码中的 test 运行时,主要会进行如下操作:

  1. googletest 构造一个 FooTest 类的对象(我们称之为 f1);
  2. f1.SetUp() 函数对 f1 进行初始化;
  3. 使用对象 f1,运行第一个 test(HandlesInput6);
  4. f1.TearDown() 在 test 完成后,进行清理工作;
  5. 对象 f1 被析构。
  6. 上述5个步骤在另一个 FooTest 类的对象(如 f2)中重复,此次会运行 HandlesInput5。

编译并执行上述代码,结果如下:

3 调用 Test

在上面的代码示例中我们能够看到,调用 Test 的操作是通过 RUN_ALL_TESTS() 宏完成的。

RUN_ALL_TESTS() 宏在所有 test 都成功时,返回0;否则返回1。需要注意的是,RUN_ALL_TESTS() 会运行所有关联的 test,这些 test 可以来自不同的 Test Case,甚至不同的源文件。

当我们调用 RUN_ALL_TESTS() 宏的时候,会进行以下操作:

  1. 保存所有 googletest flag 的状态;
  2. 为第一个 test 创建一个 test fixture 对象;
  3. 通过 SetUp() 对上一步创建的 test fixture 对象进行初始化;
  4. 使用 test fixture 对象运行 test;
  5. 通过 TearDown() 清理 fixture;
  6. 删除 fixture;
  7. 还原所有 googletest flag 的状态;
  8. 为下一个 test 重复上述操作,直到所有的 test 执行完成。

注意:main() 函数必须要返回 RUN_ALL_TESTS() 宏的结果。同时,RUN_ALL_TESTS() 只能运行一次,多次调用会与 GoogleTest 的一些功能(如 thread-safe death tests)发生冲突。

4 编写main()函数

编写 main() 函数时,要返回 RUN_ALL_TESTS() 宏的值。

main() 函数中的 ::testing::InitGoogleTest() 函数将会解析命令行中的 GoogleTest 参数,它允许用户通过多样的命令行参数来控制测试程序的行为(即定制命令行参数的功能)。需要注意的是,::testing::InitGoogleTest() 函数必须要在 RUN_ALL_TESTS() 之前调用,否则对应的 flag 可能不会被正常地初始化。

5 备注

Google Test 是线程安全的,其线程安全特性要依赖 pthreads 库。

GoogleTest测试框架介绍(二)相关推荐

  1. 单元测试及NUnit测试框架简介(二)

    一.单元测试框架的选择 在选择单元测试框架时,可以从以下几个方面去考虑: 支持自动检测注册用例:框架能否支持简单地构造用例并自动注册测试用例到测试框架中: 支持测试Fixture:即是否支持为一组测试 ...

  2. Pytest测试框架(二):pytest 的setup/teardown方法

    系列文章目录 Pytest测试框架(一):pytest安装及用例执行 Pytest测试框架(二):pytest 的setup/teardown方法 Pytest测试框架(三):pytest fixtu ...

  3. 乐玩自动化测试模块_五大测试框架介绍,附带全套黑马自动化测试视频教程(完结)...

    这个框架需要开发数据表和关键字,这些数据表和关键字独立于执行它们的测试自动化工具,并可以用来"驱动"待测应用程序和数据的测试脚本代码,关键宇驱动测试看上去与手工测试用例很类似. 概述 在自动 ...

  4. TestNG测试框架介绍整理

    TestNG学习 什么是TestNG 添加pom maven依赖 Idea创建module 注解之@BeforeMethod和@AfterMethod 注解之@BeforeClass和@AfterCl ...

  5. python pytest测试框架介绍四----pytest-html插件html带错误截图及失败重测机制

    一.html报告错误截图 这次介绍pytest第三方插件pytest-html 这里不介绍怎么使用,因为怎么使用网上已经很多了,这里给个地址给大家参考,pytest-html生成html报告 今天在这 ...

  6. 自动化测试===Httprunner测试框架介绍

    项目地址: https://github.com/HttpRunner/HttpRunner 中文手册: http://cn.httprunner.org/ 首先是环境搭建: pip install ...

  7. allure 测试报告本地打开_Pytest和Allure测试框架(二)

    七, 单元自动化测试pytest和allure在测试中应用 自动执行 1, 单元测试测试报告展示 2, conftest中编写driver,范围session,使用 addfinalizer在测试结束 ...

  8. 自动化测试--实现一套完全解耦的简单测试框架(二)

    一:每次运行都需要打开代码工具,如eclipse或者IDE等.为了后面的持续集成,直接使用Maven命令去运行自动化测试,需要引入surfire插件.笔者使用的是2.10版本Surefire和6.9. ...

  9. 移动安全测试框架MobSF(二):动态分析

    MobSF框架之动态分析 一.使用配置 [1]方式一:虚拟设备,配置动态分析器(VirtualBox + MobSF_VM.ova) 参考:https://github.com/ajinabraham ...

  10. [翻译]pytest测试框架(二):使用

    此文已由作者吴琪惠授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 调用pytest 调用命令: python -m pytest [...] 上面的命令相当于在命令行直接调用 ...

最新文章

  1. 绝地服务器维护7月5日,绝地求生7月5日更新到几点 吃鸡更新维护公告
  2. php kml文件解析,英语翻译中文:详细分析了KML、MapInfo文件及二者之间的联系,以KML点标记文件为例,基于PHP编程实现了KML到...
  3. GWT的渐进式Web应用程序配方
  4. ar 和 nm 用法
  5. 织梦文章添加字段填栏目id,内容页调用字段里的栏目文章
  6. rabbitmq延迟队列相关
  7. 信息学奥赛一本通(1012:计算多项式的值)
  8. 【工程项目经验】查看gcc arch编译选项
  9. Android【报错】xxx cannot be resolved to a type 错误解决方法
  10. unity3d ppsspp模拟器中的post processing shader在unity中使用
  11. @Value竟然能玩出这么多花样,涨知识了
  12. 雷课堂(THUnderClass)——清华大学2020C++大作业个人项目记录与总结
  13. 移动铁通宽带上网设置教程
  14. CnOpenData中国上市公司公告数据简介
  15. PP实施经验分享(24)——ECN应用及系统操作
  16. 三本可爱小表妹,面试小米Java技术岗经验分享(已拿offer)
  17. source insight 3.5设置代码注释字体
  18. 新手怎么租用传奇服务器
  19. 图片转换工具类 base64、Uri转String
  20. falcon常用参数解析

热门文章

  1. 全面详解c语言使用cJSON解析JSON字符
  2. ElasticSearch + Logstash进行数据库同步
  3. vs binsum
  4. 基于SourceTree 下的 Git Flow 模型
  5. From Apprentice To Artisan 翻译 08
  6. WPF 中依赖属性的继承(Inherits)
  7. Winform使用BackgroundWorker组件进行异步编程
  8. ASP.NET 2.0的编译行为
  9. VPC2007与VServer2005R2比较
  10. phpstudy设置允许远程访问mysql数据库