• 该测试类可以为多个测试用例共用,即可以有多个case入口与之绑定;( 下同,测试类基本都是这样,方便复用
  • 使用相关宏进行声明定义;
  • line130为该case入口;
  • line125定义类型参数Types,当运行时会遍历该参数列表,执行case的入口;
  • 其中line127、128声明并绑定了测试用例和参数对象;
  • line135注册了该测试用例;
  • 注意,绑定了定义的测试类后,case入口就可以访问类的成员,比如这里是成员函数ConverterTest(),进而遍历执行case,所以运行测试用例时控制套会显示执行了5个用例;

3.继承testing::TestWithParam<T>

3.1.适用场景

  • 看类型就知道和参数有关,是的,参数化测试;
  • 什么?一个不够?还需要测试XX场景下的?还需要测试大数据量调用情况?还需要...,批量产生测试数据,并应用测试;
  • 当然也可以灵活的使用,即可以应用其一部分长处,我曾经写过一个测试场景是不用其参数化的长处,而在其构建函数和SetUp函数中构造好一份测试对象,再用多个不同case的入口,测试该对象的不同功能接口,比如分别测增删改查相关的接口;当然这里也可以利用其参数化几何的特点,批量构造对象,批量测试...看自己测试的场景和目的了;

3.2.示例

这里展示测试Escape字符串的接口,StrCotent0为原始字符串,StrCotent0为Escape之后的字符串,当然因为特殊情况,有些字符串不需要Escape,用NeedEscape来标记;

struct EscapeData
   EscapeData(string strContent0, string strContent1, bool needEscape)
      StrContent0 = strContent0;
      StrContent1 = strContent1;
      NeedEscape = needEscape;
   string StrContent0;
   string StrContent1;
   bool NeedEscape;
class TestEscapeString : public testing::TestWithParam<EscapeData>
protected:
   void SetUp() override;
protected:
   bool mNeedEscape;
   string mStrContent0;
   string mStrContent1;
  • SetUp函数类似于初始化函数,每次用例执行(在此为遍历每一个参数执行时)首先都要执行SetUp函数 ;
  • testing::TestWithParam<T>测试参数为T,可以访问T类型的成员;
  • 即对测试参数的数据做进一步的处理,方便测试或有意为之;
void TestEscapeString::SetUp()
   mStrContent0 = GetParam().StrContent0;
   mStrContent1 = GetParam().StrContent1;
   mNeedEscape = GetParam().NeedEscape;
  • GenerateEscapeData函数为批量的创建测试参数;
  • 上文说过SetUp函数对测试参数做了进一步解析和处理,并将结果保存在成员字段里;
  • TEST_P为入口函数,此处可以访问测试类的成员,即可以访问测试数据(为方便测试而处理后的);
  • 进而测试相关接口;
INSTANTIATE_TEST_CASE_P(ESCAPE, TestEscapeString, testing::ValuesIn(GenerateEscapeData()));
TEST_P(TestEscapeString, caseEscapeUnEscape)
   string strConvert;
   string strConvert2;
   bool bNeed = JSONInterface::NeedUnEscape(mStrContent0, strConvert);
   ASSERT_EQ(bNeed, mNeedEscape);
   if (!bNeed)
      return;
   ASSERT_EQ(strConvert, mStrContent1);
   //  此处省略
  • 再结合TEST宏进一步丰富测试用例,它不香吗?
TEST(testRetoreEscapeSpecificPropertyChar1, testRetoreEscapeSpecificPropertyChar)
    //  此处省略

4.Mock模拟行为

4.1适用场景

当数据格式已设计好,数据生成方和数据使用方可以同时开发,这时候数据使用方需要按照约定格式模拟相关接口;

当需要调用后端服务接口,而此接口还在开发中未开放,需要模拟接口;

其他场景。

4.2.示例

4.2.1.待测试接口

class ParseFileUtils : public ParseFileBase
public:
   ParseFileUtils();
   virtual ~ParseFileUtils();
   shared_ptr<char> ParseBinaryFile(wstring filePath) override;
   vector<vector<string>> ParseTextFileToGetComponents(wstring textFilePath, string flag) override;
   vector<vector<string>> ParseTextFileToGetComponents(wstring textFilePath, string beginFlag, string endFlag) override;

4.2.2.测试代码编写

  • 需要编写测试类,继承被测试类;
  • 并声明要Mock哪些接口;
  • 在测试时使用测试类代替被测试类,并预先定义调用接口时有什么行为(支持多种类型的行为,在不同测试用例下模拟不同行为);
class MockParseFileUtils : public ParseFileUtils
public:
   MockParseFileUtils()
      Init();
   MOCK_METHOD1(ParseBinaryFile, shared_ptr<char>(wstring filePath));
   MOCK_METHOD2(ParseTextFileToGetComponents, vector<vector<string>>(wstring textFilePath, string flag));
   MOCK_METHOD3(ParseTextFileToGetComponents, vector<vector<string>>(wstring textFilePath, string flag, string endFlag));
   shared_ptr<char> GetBinaryStream();
protected:
   void Init();
   //  此处省略
protected:
   //  此处省略
  • 该测试类可以为多个测试用例共用,即可以有多个case入口与之绑定;
  • 针对文件无效场景的测试用例;
  • 预先定义什么条件下条用接口会有什么行为,这里是模拟无效文件,所以返回nullptr和空数组;
using ::testing::Return;
using ::testing::_;
TEST(MockParseModelFile, MockBadModelFile)
   //  Mock解析文件接口,返回模拟数据
   MockParseFileUtils obj;
   EXPECT_CALL(obj, ParseBinaryFile(testing::_)).Times(1).WillOnce(Return(shared_ptr<char>(nullptr)));
   EXPECT_CALL(obj, ParseTextFileToGetComponents(testing::_, testing::_)).Times(1).WillOnce(Return(vector<vector<string>>()));
   EXPECT_CALL(obj, ParseTextFileToGetComponents(testing::_, testing::_, testing::_)).Times(1).WillOnce(Return(vector<vector<string>>()));
   ViewDataInfo dataInfo(L"UTV", L"NAME", L"Case1", L"VIEWLOCMOCK", L"PROPLOCMOCK", L"THUMBLOCMOCK");
   Exporter exporter(dataInfo, L"D:\\TestFile\\Mock", &obj);
   Result* result = exporter.Run();
  • 该测试类可以为多个测试用例共用,即可以有多个case入口与之绑定;
  • 针对文件正常场景的测试用例;
  • 预先定义什么条件下条用接口会有什么行为,这里是模拟正常文件,所以调用其他函数返回模拟的正常数据;
TEST(MockParseModelFile, MockNormalModelFile)
   //  Mock解析文件接口,返回模拟数据
   MockParseFileUtils obj;
   EXPECT_CALL(obj, ParseBinaryFile(testing::_)).Times(1).WillOnce(Return(obj.GetFileBinaryStream()));
   EXPECT_CALL(obj, ParseTextFileToGetComponents(testing::_, testing::_)).Times(1).WillOnce(Return(vector<vector<string>>()));
   EXPECT_CALL(obj, ParseTextFileToGetComponents(testing::_, testing::_, testing::_)).Times(1).WillOnce(Return(vector<vector<string>>()));
   //  此处省略
  • 当然可以定义多种条件下接口的行为,有兴趣的可以多多尝试;
  • 别忘了测试项目(可执行程序exe)的入口为:
int _tmain(int argc, _TCHAR* argv[])
   testing::InitGoogleTest(&argc, argv);
   testing::InitGoogleMock(&argc, argv);
   int nRe = RUN_ALL_TESTS();
   system("pause");
   return nRe;

5.原理及流程

  • 根据自己的使用和理解,绘制了一张GTest/GMock测试原理流程图,供参考,
上一篇博客讲述了开发阶段编写单元测试的意义,对此不再做赘述,实战用法如下。1.TEST1.1.适用场景用法简单,几乎适用于任何单一接口的测试; 真是一直用一直爽;1.2.示例TEST(Normal, NormalTest){ ASSERT_EQ(Setting::IsSqlConnected());}2.继承testing::Test2.1.适用场景当测试一系列与类型相关的重载接口或功能相近的接口时; 其他与类型相关的场景; 灵活运用,利用其部分特点创造.
catch_gmock_integration 当使用 catch.hpp 测试框架时,允许 EXPECT_CALL 和其他 gmock 函数工作的代码倾倒场。 随意从这个 repo 中窃取。 我不关心许可证,会接受拉取请求。 这是概念证明,而不是库。 git clone mkdir build && cd build cmake .. && make && make test 肉在哪里? ./test/suite1/gmock_catch_interceptor.cpp ./test/suite1/main.cpp 注意主要仍然初始化谷歌测试。 GMock 依赖 GTest 进行编译,不知道为什么。 我删除了打印到屏幕/输出文件的默认侦听器。 安装了一个侦听器以具有 GMock 的挂钩点。 GMock 在模拟对象的拆卸时执行,然后作为生命周期的一部分通知侦听器。
项目级C语言单元测试框架, 一键生成, 无代码侵入 支持gtest gmock语法, 支持桩函数开关,真实/模拟随时切换 自动打桩 ,自动编译 ,提高 编码效率 代码质量, 快速入门 代码覆盖率自动显示,详细的项目级测试报告 windows linux 嵌入式环境,多平台支持,支持命令行与GUI界面。
gtest是谷歌为C++开发的单元测试框架,该框架基于xUnit架构。gtest提供了较丰富的测试特性,且其命令行方式输出界面友好美观,是C++单元测试工具的较佳选择。 1 gtest环境部署 先从这里下载到gtest源码包,解压后执行如下命令: ./configure 这里google没有提供make install行为来安装,我们需要手动安装。继续执行以下命令: cp li
      有时为了完整的测试一个函数的正确性,我们需要测试给定各种不同输入的情况下,函数的输出是否正确。最直接的方法就是我们手动去给不同输入,然后测试输出是否正确。但是这种方式工作量大,并且都是重复性,无意义的操作。为此,gtest中提供了参数化的测试。 2、参数化测试使用方法     要使用参数化测试,我们需要创建一个子类继承testing::TestWithParam
文章目录前言1. 下载网址2. 为什么选择Google Mock3. C++简单的例子3.1 使用流程4. 指定自己的期望   在进行单元测试时,我们想要测试自己缩写函数A,但是函数A却依赖于函数B,当函数B无法满足预期时就无法对函数A进行测试,主要由于下面几个原因: 函数B依赖于硬件设备 真实的函数B的返回值无法满足我们的预期 团队开发中函数B尚未实现   这时就需要对函数B进行打桩(仿真mock),使其达到我们预期的效果。 但是如同下面这种类型函数时,则需要深入下去,对基层的函数进行打桩:
目录一、简单Demo、断言2.1 ASSERT和EXPECT2.2 流三、测试TEST()四、调用测试和main() 上文(C++开发测试工具gmock的安装与使用超详解)介绍了gmock的安装、配置与基本使用案例,本文将详细介绍一下gmock的基本语法,结合上文一起食用效果更佳哦~ 一、简单Demo 首先来编写一个简单Demo,编写代码之前,首先需要将解决方案的平台与目标程序一致,这里选择的是x64,然后版本也要与目标程序一致,这里选择的是release版本。 新建一个头文件,命名为demo.h,声明