首页 > 其他分享 >gtest测试用例打印台内容重定向

gtest测试用例打印台内容重定向

时间:2023-01-15 23:45:28浏览次数:49  
标签:case name 打印台 GTEST TEST gtest 测试用例 test

需求描述

在使用 gtest 做测试时,有时候需要记录测试过程中,测试对象运行时打印在控制台的相关内容,并根据打印的内容做校验,判断用例是否通过。

由于测试用例很多,我们希望能够根据测试集合和测试用例,自行建立具有层级关系的目录文件夹,将打印的内容以 txt 文档格式保存起来,便于后期整理测试报告。

需求分析

为解决上述需求,拆解出两个待实现功能:

  1. 打印内容重定向
  2. 测试集合和测试用例的名字获取

功能1:打印台内容重定向。

使用 freopen来实现。以下是一个小 demo。

int conSoleId; 
char logSaveFile[50] = "log.txt";
// [1]. 记录打印台id
conSoleId = dup(1);  
// [2]. 控制台信息重定向到文本
FILE* fp = freopen(logSaveFile, "w", stdout); 
// [3]. 测试代码
// your test code here
// [4]. 重新定向到控制台
dup2(conSoleId, 1);

功能2:测试集合和测试用例的名字获取。

gtest 的 TEST_F 是预处理宏定义,通过一层层的分析代码调用关系,可以发现,我们使用该宏时,实际上是先根据输入的测试集合和测试用例名字构建类,使之构成继承关系。接着注册用例信息,最后再把类中的测试内容函数TestBody()留给我们自己来写测试内容。

  • 首先 TEST_F 的内容实际由 GTEST_TEST_ 来实现
#define TEST_F(test_fixture, test_name)\
  GTEST_TEST_(test_fixture, test_name, test_fixture, \
              ::testing::internal::GetTypeId<test_fixture>())
  • 然后 GTEST_TEST_ 组织代码,实现了类的继承,和类内成员变量、函数的构建,最后将 TestBody() 函数体的具体内容交给使用者去定义。
// Helper macro for defining tests.
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
 public:\
  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
 private:\
  virtual void TestBody();\
  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
  ::test_info_ =\
    ::testing::internal::MakeAndRegisterTestInfo(\
        #test_case_name, #test_name, NULL, NULL, \
        ::testing::internal::CodeLocation(__FILE__, __LINE__), \
        (parent_id), \
        parent_class::SetUpTestCase, \
        parent_class::TearDownTestCase, \
        new ::testing::internal::TestFactoryImpl<\
            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()

在该类中的成员变量类型 TestInfo,定义如下:

class GTEST_API_ TestInfo {
 public:
  // Destructs a TestInfo object.  This function is not virtual, so
  // don't inherit from TestInfo.
  ~TestInfo();

  // Returns the test case name.
  const char* test_case_name() const { return test_case_name_.c_str(); }

  // Returns the test name.
  const char* name() const { return name_.c_str(); }

  // Returns the name of the parameter type, or NULL if this is not a typed
  // or a type-parameterized test.
  const char* type_param() const {
    if (type_param_.get() != NULL)
      return type_param_->c_str();
    return NULL;
  }

其中的 test_case_name() 可获取测试集合名,name() 可获取测试用例名。

因此在测试内容部分,我们可这样获取测试集合名和测试用例名:

TEST_F(PROCUT_TEST_EXAMPLE, say_hello)
{
	char test_case_name[50] = this->test_info_->test_case_name();
    char test_name[50] = this->test_info_->name();
}

需求实现

为了便于使用,将以上代码整合成一组宏:

// 测试结果存放的目录路径
std::string rootPath = "..\\..\\..\\data\\sit_test";

#define CONSOLE_TO_TXT_START \
int conSoleId;\
char logSavePath[100],mkDirCmd[100],nowTime[100],logSaveFile[100];\
sprintf(logSavePath,"%s\\%s\\%s",rootPath.c_str(),this->test_info_->test_case_name(),test_info_->name());\
sprintf(mkDirCmd,"if not exist \"%s\" (mkdir \"%s\")",logSavePath,logSavePath);\
system(mkDirCmd);\
time_t t = time(nullptr);\
struct tm* now = localtime(&t);\
strftime(nowTime, sizeof(nowTime), "%Y_%m_%d@%H_%M_%S", now);\
sprintf(logSaveFile,"%s\\log_%s.txt",logSavePath,nowTime);\
conSoleId = dup(1);\
FILE* fp = freopen(logSaveFile, "w", stdout);\
fflush(fp);\

#define CONSOLE_TO_TXT_END \
dup2(conSoleId, 1);\

在使用时可以这样调用:

TEST_F(PROCUT_TEST_EXAMPLE, say_hello)
{
    CONSOLE_TO_TXT_START
	// your test code here
    CONSOLE_TO_TXT_END
    SUCCEED();
}

这样我们在运行完该用例后,可以在 "..\..\..\data\sit_test\PROCUT_TEST_EXAMPLE\say_hello"路径下获得一份名字形如 log_2023_01_15@13_21_49.txt 的文档。

参考资料

标签:case,name,打印台,GTEST,TEST,gtest,测试用例,test
From: https://www.cnblogs.com/gshang/p/gtest_console_to_txt.html

相关文章

  • c++ unit test via gtest
    //model/book.h#pragmaonce#include<iostream>usingnamespacestd;classbook{public:book()=default;~book()=default;book(constbook&......
  • gtest
    提供两种判断的宏EXPECT_XXX()(推荐使用) ASSERT_XXX()(出错直接crash)分组测试#include<gtest/gtest.h>intFactorial(intn){intresult=1;for(inti=1......
  • Selenium 测试用例编写
    ​​原文链接​​编写Selenium测试用例就是模拟用户在浏览器上的一系列操作,通过脚本来完成自动化测试。编写测试用例的优势:开源,免费。支持多种浏览器IE,Firefox,Chrome,Safar......
  • Docker搭建测试用例平台 TestLink
    Testlink是基于WEB的测试用例管理系统,主要功能是:测试项目管理、产品需求管理、测试用例管理、测试计划管理、测试用例的创建、管理和执行,并且还提供了统计功能。Testlink......
  • Selenium62-使用POM的测试用例
    添加赛区脚本test_后台_双创_基础设置_赛区管理_添加赛区_case_v7.py导入各个网页对象改造to_division_manager导入各个网页对象导入各个网页对象:frompage.后台_主页_page......
  • 5.测试用例
    测试用例TestCase作用:为特定的目的而设计的一组测试输入、执行条件和预期结果的文档  测试用例八大要素用例编号用例标题所属项目用例级别预置条件测试......
  • 回归测试用例选择方法
    1、回归测试就是修改完bug后对程序的新一轮测试。根据微软的统计,按照他们的经验,一般开发人员解决3~4个bug会衍生出一个新的bug,这就是必须作回归测试的原因。2......
  • Selenium62-使用POM的测试用例
    添加赛区脚本test_后台_双创_基础设置_赛区管理_添加赛区_case_v7.py导入各个网页对象改造to_division_manager导入各个网页对象导入各个网页对象:frompage.......
  • Selenium25-TestCase(测试用例)
    TestCase(测试用例)#导入unittest包importunittest#测试类(名称自定义)只要继承unittest模块中TestCase类即可classMyTestCase(unittest.TestCase):#书写测......
  • 测试用例设计指南(五)
    画出其对应的控制流图如下:​​​​逐一:如果在程序中遇到复合条件,例如条件语句中的多个布尔运算符(逻辑OR、AND)时,为每一个条件创建一个独立的节点,包含条件的节点称为判定节点......