技术贴 | 一文掌握 Google Test 框架

news2024/11/20 1:20:52

在这里插入图片描述

一、简介

1. 引言
在开发过程中,如何保证代码的质量以及程序的正确性成为了我们亟需解决的问题,其中测试用例成为了不必可少的一部分。测试用例不仅可以帮助我们验证代码的正确性,还能帮助我们捕获潜在的错误,提高代码的可靠性和可维护性。然而手动编写和执行测试用例可能会非常繁琐和耗时,因此我们引入了 Google Test 框架。
2. Google Test 框架
Google Test (gtest) 是一个由 Google 开发的流行的 C++ 单元测试框架。它为开发者提供了一套强大的工具和功能,用于编写、组织和运行测试用例。gtest 框架支持测试驱动开发(Test-Driven Development,TDD)和行为驱动开发(Behavior-Driven Development,BDD)方法。
具有以下主要功能和特点:

简单易用
gtest 框架提供了简洁而直观的语法和 API,使得编写测试用例变得简单易懂。通过使用宏和断言,开发者可以轻松地定义测试用例和验证预期结果;

丰富的断言
gtest 框架提供了一组丰富的断言宏,用于验证测试结果。这些断言宏包括比较值、检查条件、抛出异常等功能,可以满足各种测试需求;

灵活的测试组织
gtest 框架允许开发者将测试用例组织成测试套件(Test Suite),并可以嵌套多个测试套件。这样可以更好地组织和管理测试用例,提高测试代码的可读性和可维护性;

测试夹具支持
gtest 框架提供了测试夹具(Test Fixture 的概念,允许开发者在多个测试用例之间共享资源或设置环境。通过派生测试夹具类并重写 SetUp() 和 TearDown() 方法,开发者可以方便地进行资源的初始化和清理操作;

完善的编译及平台支持
gtest 框架支持 C++11 及以上的 C++ 标准,支持 Linux、MacOS、Windows 等众多平台,支持 gcc5.0+、clang5.0+、MSVC2015+ 编译器,支持 Bazel 以及 cmake 构建工具;

丰富的测试报告
gtest 框架生成详细的测试报告,显示每个测试用例的运行结果,包括通过的用例和失败的用例。如果断言失败,报告会提供失败的原因和位置,方便开发者快速定位问题。

二、Google Test 框架集成

1. 系统安装 gtest 测试框架
Ubuntu:

sudo apt install libgtest-dev

Centos:

https://pkgs.org/search/?q=gtest # 下载gtest-devel.rpm
rpm -ivh gtest-devel.rpm         # 安装rpm包

2. CMake 项目集成
Cmakelists.txt 文件中添加以下代码:

enable_testing() # 开启测试,否则无法执行make test
add_executable(add_test_exe add_test.cpp) # 添加可执行程序
target_link_libraries(add_test_exe PRIVATE gtest pthread) # 链接gtest库
add_test(add_test_exe ${CMAKE_BINARY_DIR}/add_test_exe) # 添加测试,保证make test可以执行该测试用例

3. 简单 Demo
add_test.cpp:


#include <gtest/gtest.h>

int add(int a, int b) {
  return a + b;
}

TEST(TEST_ADD, UNSIGNED_INT_VALUE) {  
  int result = add(100, 200);  
  EXPECT_EQ(result, 300);  
  result = add(200, 300);  
  EXPECT_NE(result, 400);
}

int main() {
  testing::InitGoogleTest();
  return RUN_ALLTESTS();
}

4. 编译运行

~/Projects/Test master +625 !5592 ?1 ) mkdir build && cd build && cmake .. && make  -j4
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler:/usr/bin/cc
-- Check for working CXX compiler:/usr/bin/c++
-- Configuring done
-- Generating done
-- Build files have been written to:/home/limstor/Projects/Test/build
Scanning dependencies of target add_test_exe
[50%] Building CXX object CMakeFiles/add_test_exe.dir/aadd_test.cpp.o
[100%] Linking CXX executable add_test_exe
[100%] Built target add_test_exe
~/Projects/Test/build master +625 !5592 ?2)/add_test_exe
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from TEST_ADD
[ RUN      ]TEST_ADD.UNSIGNED_INT_VALUE
[       OK ]TEST_ADD.UNSIGNED_INT_VALUE (O ms)
[----------] 1 test from TEST_ADD (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0ms total)
[  PASSED  ] 1 test.

三、Google Test - 测试宏

1. TEST 宏
说明:该宏定义用来测试其内部代码,其内部断言决定最终的测试结果。
使用方式:

TEST(TestSuiteName, TestName) {
  ... statements ...
}

用途:针对多个用例之间不需要进行数据共用的测试场景。

示例:

int add(int a, int b) {
  return a + b;
}

TEST(TEST_ADD, UNSIGNED_INT_VALUE) {
  int result = add(100, 200);
  EXPECT_EQ(result, 300);
  result = add(200, 300);
  EXPECT_NE(result, 400);
}

TEST(TEST_ADD, NEGATIVE_INT_VALUE) {
  int result = add(-100, -200);
  EXPECT_EQ(result, -300);
  result = add(-200, -300);
  EXPECT_NE(result, -400);
}

2. TEST_F 宏
说明:该宏定义用来对 TestFixtureName 类进行多样测试。
使用方法:

TEST_F(TestFixtureName, TestName) {
  ... statements ...
}

用途:针对多个用例之间需要进行数据共用的测试场景,用于多样测试,也有助于简化测试代码。

使用示例:

class Student {
public:
  Student(int id, std::string name): id_(id), name_(name) {};
  ~Student() = default;
  void SetAge(int age) { age_ = age; }
  int GetAge() const { return this->age_; }
  void SetScore(int score) { score_ = score; }
  int GetScore() const { return this->score_; }
private:
  int id_;
  std::string name_;
  int age_;
  int score_;
};
class StudentTest : public testing::Test {
protected:
  void SetUp() override {
    student = new Student(1234, "Tom");
  }
  void TearDown() override {
    delete student;
  }
  Student* student;
};
TEST_F(StudentTest, SET_AGE_TEST) {
  student->SetAge(16);
  int age = student->GetAge();
  EXPECT_EQ(age, 16);
}
TEST_F(StudentTest, SET_SCORE_TEST) {
  student->SetScore(99);
  int score = student->GetScore();
  ASSERT_EQ(score, 99);
}
int main() {
  testing::InitGoogleTest();
  return RUN_ALL_TESTS();
}

3. TEST_P 宏
说明:该宏定义用来参数化测试。
使用方式:

TEST_P(TestFixtureName, TestName) {
  ... statements ...
}

用途:当待测试方法的行为取决于传入的参数时,而且这些参数的不同组合有多种, 而你又不想为此写多个类似的 test case 时,可以用参数化测试。
示例:


struct TestData {
  int  a;
  int  b;
  int  result;
  char type;
};
class CalculateTest : public ::testing::TestWithParam<TestData> {
protected:
  void checkData() {
    int a = GetParam().a;
    int b = GetParam().b;
    int result = GetParam().result;
    switch (GetParam().type) {
      case '+':
        EXPECT_EQ(a + b, result);
        break;
      case '-':
        EXPECT_EQ(a - b, result);
        break;
      case '*':
        EXPECT_EQ(a * b, result);
        break;
      case '/':
        EXPECT_EQ(a / b, result);
        break;
      default:
        break;
    }
  }
};
TEST_P(CalculateTest, Test) {
  checkData();
}
INSTANTIATE_TEST_SUITE_P(TestMyClassParams,
                         CalculateTest,
                         ::testing::Values(
                           TestData{100, 200, 300, '+'},
                           TestData{20, 5, 15, '-'},
                           TestData{5, 6, 30, '*'},
                           TestData{8, 2, 3, '/'}
                         ));
int main() {
  testing::InitGoogleTest();
  return RUN_ALL_TESTS();
}

四、Google Test - 断言

断言:对测试代码中的检查点进行检查。分为以下两种断言类型:

  • ASSERT_*断言:当检查点失败时,退出当前函数;
  • EXPECT_*断言:当检查点失败时,继续往下执行。
  1. 布尔值检查
    在这里插入图片描述

  2. 字符串类型检查
    在这里插入图片描述

  3. 数值类型检查
    在这里插入图片描述

  4. 返回成功或失败
    在这里插入图片描述

  5. 返回成功或失败
    在这里插入图片描述

  6. 谓词断言
    在这里插入图片描述

  7. 浮点数检查
    在这里插入图片描述

  8. Windows 平台的 HRESULT 检查
    在这里插入图片描述

  9. 类型检查
    testing::StaticAssertTypeEq(); 类似模板中的编译检查

除以上 9 种断言使用方法外,还可以在断言后增加自定义信息输出

EXPECT_EQ(a, b) << "Vectors x and y differ at index "

五、Google Test - 事件机制

gtest 提供了多种事件机制:

  • 全局事件:所有用例执行前后;
  • TestSuite 级别:同一 TestSuite 的第一个用例前,最后一个用例执行后;
  • TestCase 级别:每个测试用例前后。
    1. 全局事件
    要实现全局事件,必须写一个类,继承 testing::Environment 类,实现里面的 SetUp 和 TearDown 方法:
    SetUp() 方法在所有用例执行前执行;
    TearDown() 方法在所有用例执行后执行。

示例:

class FooEnvironment : public testing::Environment {
public:
  virtual void SetUp() {        
    std::cout << "Foo FooEnvironment SetUP" << std::endl;    
  }    
  virtual void TearDown() {        
    std::cout << "Foo FooEnvironment TearDown" << std::endl;    
  }
};

注意:在执行用例之前,需要在 main 函数中通过 testing::AddGlobalTestEnvironment 方法将事件挂载进来。

示例:

int main() {    
  testing::AddGlobalTestEnvironment(new FooEnvironment);    
  testing::InitGoogleTest();    
  return RUN_ALL_TESTS();}

2. TestSuite 事件
要实现 TestSuite 事件,必须写一个类,继承 testing::Test 类,实现 SetUpTestCase 和 TearDownTestCase 方法:
SetUpTestCase() 方法在 TestSuite 里的第一个 TestCase 之前执行;
TearDownTestCase() 方法在 TestSuite 里的最后一个 TestCase 之后执行。

示例:


class FooTest : public testing::Test {
 protected:  
  static void SetUpTestCase() {
    shared_resource_ = new int(1234);  
  }  
  static void TearDownTestCase() {    
    delete shared_resource_;    
    shared_resource_ = NULL;  
  }  
  int* shared_resource_;
};

3. TestCase 事件

实现方法和 TestSuite 事件几乎一样,只不过它是实现的 SetUp 和 TearDown 方法:
(1) SetUp() 方法在每一个 TestCase 之前执行;
(2) TearDown() 方法每一个 TestCase 之后执行。

示例:


class FooCalcTest:public testing::Test {
protected:
    virtual void SetUp() {
      m_foo.Init();    
    }    
    virtual void TearDown() {    
      m_foo.Finalize();    
    }    
    FooCalc m_foo;
};

六、Google Test - 命令行参数

在测试用例二进制文件后执行以下参数:

1. --gtest_list_tests

使用这个参数时,将不会执行里面的测试用例,而是输出测试用例的列表。

2. --gtest_filter

对执行的测试用例进行过滤,支持通配符。
? 单个字符
* 任意字符
- 排除,如,-a 表示除了 a
: 取或,如,a:b 表示 a 或 b

比如下面的例子:


./foo_test 没有指定过滤条件,运行所有用例
./foo_test --gtest_filter=* 使用通配符*,表示运行所有用例
./foo_test --gtest_filter=FooTest.* 运行所有 TestSuiteName 为 FooTest 的用例
./foo_test --gtest_filter=*Null*:*Constructor* 运行所有TestSuiteName或 TestName 包含 Null 或 Constructor 的用例。
./foo_test --gtest_filter=FooTest.*-FooTest.Bar 运行所有 TestSuiteName 为 FooTest 的用例,但是除了 FooTest.Bar 这个用例。

3. --gtest_also_run_disabled_tests

执行用例时,同时也执行被置为无效的测试用例(TestSuiteName 或 TestName 以 DISABLED 为前缀)。

4. --gtest_repeat=[COUNT]

设置用例重复运行次数,例如:

–gtest_repeat=1000 重复执行1000次,即使中途出现错误。
–gtest_repeat=-1 无限次数执行
–gtest_repeat=1000 --gtest_break_on_failure 重复执行1000次,并且在第一个错误发生时立即停止。这个功能对调试非常有用。
–gtest_repeat=1000 --gtest_filter=FooBar 重复执行1000次测试用例名称为FooBar的用例。

5. --gtest_color=(yes|no|auto)

输出命令行时是否使用一些五颜六色的颜色。默认是 auto。

6. --gtest_print_time

输出命令行时是否打印每个测试用例的执行时间。默认是不打印。

7. --gtest_output=xml[:DIRECTORY_PATH|:FILE_PATH]

将测试结果输出到一个 xml 中:
–gtest_output=xml: 不指定输出路径时,默认为用例当前路径;

–gtest_output=xml:~/dir 指定输出到某个目录;

–gtest_output=xml:~/dir/foo.xml 指定输出到~/dir/foo.xml。

如果不是指定了特定的文件路径,gtest 每次输出的报告不会覆盖,而会以数字后缀的方式创建。

8. --gtest_break_on_failure

调试模式下,当案例失败时停止,方便调试。

9. --gtest_throw_on_failure

当用例失败时以 C++ 异常的方式抛出。

10. --gtest_catch_exceptions

是否捕捉异常。gtest 默认是不捕捉异常的,因此假如你的测试用例抛了一个异常,很可能会弹出一个对话框,这非常的不友好,同时也阻碍了测试用例的运行。如果想不弹框,可以通过设置这个参数来实现。如将 --gtest_catch_exceptions 设置为一个非零的数。

注意:这个参数只在 Windows 平台下有效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1154996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IO模块:钢铁安全绿色生产的智能化助手

钡铼I/O模块以其卓越的性能和可靠性&#xff0c;为钢铁行业的安全绿色生产提供了强有力的支持。这个模块拥有出色的实时监测功能&#xff0c;能够精确捕捉现场设备的工作状态&#xff0c;确保设备的正常运行。通过采用先进的预测性维护技术&#xff0c;钡铼I/O模块能够提前发现…

传统金融机构加入代币化浪潮,新一轮加密周期的重要组成部分?

新加坡金融管理局 (MAS) 成立了由日本金融厅 (FSA)、英国金融行为监管局 (FCA) 和瑞士金融市场监管局 (FINMA) 组成“守护者计划”政策制定者组&#xff08;Project Guardian&#xff09;&#xff0c;正在计划对固定收益、外汇和资产管理产品进行资产代币化试点&#xff0c;以推…

Python 的 Web 自动化测试的实践

Web 测试是软件测试中比较重要的一个分支&#xff0c;而要实现 Web 自动化测试则要求测试人员能熟练掌握自动化测试工具和编程语言。介绍免费开源的 Web 测试工具 Selenium&#xff0c;以及流行的编程语言 Python。根据自动化测试的原理&#xff0c;对网页元素的常用定位方式&a…

smartLink HW-DP新版提供更多扩展功能——用于PROFIBUS和HART系统中物联网集成

Softing工业自动化的smartLink HW-DP网关可独立于控制器访问PROFIBUS DP网络&#xff0c;且新发布的1.30固件版本还提供了更多数据连接和传输的扩展功能。 smartLink HW-DP可无缝集成到PROFIBUS网络中&#xff0c;而不会影响现有设备的运行。该网关还可为新的和现有的PROFIBUS …

非常爆火的流量卡推广上线了

流量卡推广可以通过“聚量推文”申请&#xff0c;一手渠道 现在非常火的推广项目就是流量卡推广了&#xff0c;佣金价格高 普遍的价格是几十上百块&#xff0c;你一天推广10个收入就接近4位数&#xff0c;还是比较可观的 聚量推客专注于app拉新&#xff0c;网推项目&#xff…

博客系统-项目测试

自动化博客项目 用户注册登录验证效验个人博客列表页博客数量不为 0 博客系统主页写博客 我的博客列表页效验 刚发布的博客的标题和时间查看 文章详情页删除文章效验第一篇博客 不是 "自动化测试" 注销退出到登录页面,用户名密码为空 用户注册 Order(1)Parameterized…

MyBatis-Plus使用——配置yml参数 常用的注解@Table,@TableId,@IdType,@TableField,CRUD的API接口

前言 MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 本系列博客结合实际应用场景&#xff0c;阐述MyBatis-Plus实际…

Python开发技能实战-通过配置的代理服务器在具有外网连接的环境中在Pycharm中运行python代码

实现功能 打开科学上网工具&#xff0c;使得能够在浏览器科学上网&#xff0c;通过科学上网工具的配置文件&#xff0c;可以看出本地和远程代理的映射关系&#xff0c;此时&#xff0c;远程地址本地地址&#xff0c;远程端口本地端口。 1、在程序中配置请求网页代理请求。不需…

GTS GtsUnofficialApisUsageTestCases Failed

GTS 测试GtsUnofficialApisUsageTestCases失败如下&#xff1a; junit.framework.AssertionFailedError: There are 102 violation(s) com.google.android.gm / Landroid/window/BackEvent;->getProgress()F / BLOCKED / LINKING com.google.android.gm / Landroid/window/…

java参数中的-、--、-X、-XX、-D

详细描述请参考&#xff1a;https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html Java标准选项&#xff08;以-、或者–开头&#xff09; Java标准选项被所有的Java虚拟机&#xff08;JVM&#xff09;实现所支持。 这些选项用于普通的动作&#xff0c;例如检…

服务器数据恢复-VSAN环境下ESXI虚拟机无法访问的数据恢复方案

一、用户信息&#xff1a; 广东某单位 二、数据恢复环境&#xff1a; 主机操作系统&#xff1a;ESXI 分区类型&#xff1a;VSAN 存储介质清单 &#xff1a;一共8台服务器节点&#xff0c;每节点2个磁盘组&#xff0c;其中1个磁盘组配置1块SSD固态硬盘&#xff0c;4块1.2T机…

【unity3D】Debug方法(如何在console面板中输出红色的错误信息)

&#x1f4a6;本专栏是我关于游戏开发的笔记 &#x1f236;本篇是一个简短的小知识点 Debug方法 介绍常用方法 介绍 Unity中的Debug方法可以用来输出一些调试信息&#xff0c;帮助开发者查找代码中的错误和问题。 常用方法 Debug.Log()&#xff1a;最常用的Debug方法之一&am…

表白墙(服务器)

目录 0.需求 1.创建Maven项目 2.给pom.xml内引入三个依赖 3.完善目录&#xff0c;并补充web.xml中的内容 4.编写代码 后端代码 ​编辑前端代码 5.引入数据库 创建message表 创建工具类 往MessageServlet类中添加方法 0.需求 前面写好了表白墙页面&#xff0c;但存…

视阅口译有何特点,哪里提供视阅口译翻译?

据了解&#xff0c;视阅口译是一种涉及视听和口头表达的翻译方式&#xff0c;它在跨文化交流等领域中起到了非常重要的作用。那么&#xff0c;视阅口译有何特点&#xff0c;哪里提供专业的视阅口译服务&#xff1f; 我们知道&#xff0c;视阅口译就是基于事先准备好的讲稿或文…

“构建高效的Java Web开发环境及前后端分离后台接口部署“

目录 引言一、安装环境&#xff1a;JDK和Tomcat1. 安装JDK下载jdk配置环境变量2. 安装Tomcat 二、安装MySQL三、部署前后端分离后台接口总结 引言 在现代软件开发中&#xff0c;构建高效的开发环境和部署稳定的后台接口是至关重要的。本文将介绍如何安装和配置Java开发环境&am…

一文2000字使用JMeter进行接口测试教程!(建议收藏)

安装 使用JMeter的前提需要安装JDK&#xff0c;需要JDK1.7以上版本目前在用的是JMeter5.2版本&#xff0c;大家可自行下载解压使用 运行 进入解压路径如E: \apache-jmeter-5.2\bin&#xff0c;双击jmeter.bat启动运行 启动后默认为英文版本&#xff0c;可通过Options – Cho…

【王道代码】【3 栈和队列】

结构体定义&#xff1a; 队列操作&#xff1a;

DevExpress(GridControl基础样式)

1.设置GridControl底部导航器可见 this.gridControl1.UseEmbeddedNavigator true; 2.隐藏嵌入式导航器的追加按钮&#xff0c;所有导航器的操作可以自行查阅API this.gridControl1.EmbeddedNavigator.Buttons.Append.Visible false; 3.去掉第一列前的空白列&#xff0c;去掉…

学历不好,背景不强?想进入互联网行业难道真的没希望?

随着互联网的大环境越来越好&#xff0c;各个企业又有了新一轮的招聘需求&#xff0c;但是大家会发现企业招人要求出奇的一致&#xff1a;学信网可查、本科及以上学历&#xff01;虽然越来越多的人希望能够进入这个行业&#xff0c;但是有些人可能会因为学历不好或者背景不强而…