GoogleTest使用

断言

​ 断言是 gtest 核心组成,所有的测试用例最终都是以断言实现的。

​ ASSERT 系列的断言如果失败,则会产生一个严重错误并导致当前作用范围的测试用例中断;

​ EXPECT 不会产生任何错误,测试用例依旧可以继续执行。

true / false 条件测试

致命 非致命 验证

ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition: true

ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition: false

失败时,ASSERT_* 产生一个致命错误,并从当前函数退出,EXPECT_* 则产生一个非致命错误,并允许函数继续运行。

二元比较

致命断言 非致命断言 验证

ASSERT_EQ(val1, val2); EXPECT_EQ(val1, val2); val1 == val2

ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2

ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2

ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2

ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2

ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2

比较 C 字符串,ASSERT_EQ 测试它们是否位于相同内存位置,而不是是否具有相同的值。因此,比较 C 字符串的值使用 ASSERT_STREQ();

当执行指针比较时使用 *_EQ(ptr, nullptr) 和 *_NE(ptr, nullptr) 而不是 *_EQ(ptr, NULL) 和 *_NE(ptr, NULL)。

字符串比较

致命断言 非致命断言 验证

ASSERT_STREQ(str1, str2); EXPECT_STREQ(str1, str2); 具有相同内容

ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); 具有不同内容

ASSERT_STRCASEEQ(str1, str2); EXPECT_STRCASEEQ(str1, str2); 相同内容忽略大小写

ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); 不同内容忽略大小写

如果宽字符串(wchar_t*, Windows 上 UNICODE 模式的 TCHAR*,或 std::wstring)被送进断言,它将在打印时被转换为 UTF-8。

断言扩展

SUCCEED() : 产生一个成功标识,只代表某一个步躁成功;

FAIL() : 产生一个严重错误,相当于一个 ASSERT 宏失败;

ASSERT_THROW(expre,type) : 断言表达式 expre 会抛出一个 type 类型异常;

ASSERTANY THROW(expre) : 断言表达式 expre 会抛出一个任意类型异常;

ASSERT_NO_THROW(expre) : 断言表达式 expre 不会抛出任何异常。

测试夹具 TEST_F

解决场景:有测试场景需要为多个测试复用相同的数据对象配置,可以方便测试

关于测试夹具的实现方式有三种,针对不同的使用场景:

成员函数

  1. 虚函数

    virtual void SetUp():类似于构造函数,在 TEST_F 之前运行;

    virtual void TearDown():类似于析构函数,在 TEST_F 之后运行。

  2. 静态函数

    static void SetUpTestSuite():在第一个 TEST 之前运行;

    static void TearDownTestSuite():在最后一个 TEST 之后运行。

  3. 全局事件

    继承 testing::Environment

​ virtual void SetUp():在所有用例之前运行;

​ virtual void TearDown():在所有用例之后运行。

创建流程:

创建一个公有继承自 ::testing::Test 的类,进行 protected 类内部声明;

编写一个默认的构造函数或 SetUp() 函数为每个 test 准备对象;

编写一个析构函数或 TearDown() 函数释放 SetUp() 中分配的资源;

完善类资源信息,使用 TEST_F 宏,第一个参数填写新建夹具类名称。

TEST_F的使用

使用 TEST_F(类名, 测试夹具名称) :

// TestFixtureName 测试夹具类名(_F:fixture)
TEST_F(TestFixtureName, TestName) {
    ... test body ...
}

通过 TEST_F() 定义的每个测试,googletest 将在运行时自动创建一个 全新的 测试夹具,立即通过 SetUp() 初始化它,运行测试,最后调用 TearDown() 清理资源,然后删除测试夹具。

测试调用

定义测试后,通过 RUN_ALL_TESTS() 运行它们,如果所有测试都成功,返回 0,否则返回 1。

调用 RUN_ALL_TESTS() 宏时:

  1. 保存所有 googletest 标记的状态;
  2. 为第一个测试创建一个测试夹具对象;
  3. 通过 SetUp() 初始化;
  4. 在测试夹具对象上运行测试;
  5. 通过 TearDown() 清理测试夹具;
  6. 删除夹具,恢复所有的 googletest 标记的状态;
  7. 为下一个测试重复上述步骤。

案例1:

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(testfixed VERSION 0.1.0)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

//这里指定google的lib和头文件路径,根据自己的实际路径设置
include_directories("~/code/yanjun/google_code/googletest/googletest/include/")
link_directories("~/code/yanjun/google_code/googletest/build/lib")

add_executable(${PROJECT_NAME} testfixed.cc)
target_link_libraries(${PROJECT_NAME} gtest gtest_maingtest_main pthread)
//下面test.cc文件中没有main函数,这里直接连接gtest_maingtest_main库(库里有main函数),也可自己写

test.cc

#include "gtest/gtest.h"
#include <iostream>
#include <deque>

class TestFA : public ::testing::Test {
public:
    TestFA() {}
    ~TestFA() {}

protected:

    //以下两个static方法会在每个TEST_F运行前后都会被调用,这里会被调用2次
    void SetUp() override {
        std::cout << "Reference count: " << deq.use_count() << std::endl;
        auto              p    = deq.get();
        auto              pxin = *p;
        std::deque< int > a(5, -1);
        std::cout << "1. size: " << pxin.size() << std::endl;
        pxin.swap(a);
        std::cout << "2. size:" << pxin.size() << std::endl;
    }
    void TearDown() override {
        deq.reset();
        deq = nullptr;
    }

    //以下两个static方法只会在第一个TEST_F之前和最后一个TEST_F之后被调用一次
    static void SetUpTestSuite()
    {
        std::cout << "SetUpTestSuite --------------------" << std::endl;
    }

    static void TearDownTestSuite()
    {
        std::cout << "TearDownTestSuite --------------------" << std::endl;
    }
public:
    std::shared_ptr< std::deque< int > > deq =
        std::make_shared< std::deque< int > >();
};


TEST_F(TestFA, isEmptyOnB) {
    EXPECT_GE(deq.use_count(), 1);
    if (deq.use_count() != 0) {
        deq.reset();
    }
}
TEST_F(TestFA, isEmptyOnBIndependence) {
    EXPECT_GE(deq.use_count(), 1);
}

分析:

1、创建类public继承自::testing::Test类,并重写SetUp和TearDown方法,在这两个方法里自定义多个测试用例复用的资源创建及释放

2、TEST_F() 定义的每个测试用例,googletest 将在运行时自动创建一个 全新的 测试夹具,立即通过 SetUp() 初始化 它,运行测试,最后调用 TearDown() 清理资源,然后删除测试夹具。多个TEST_F()拥有相互独立的个体,数据不会相互影响。

案例2:

继承自testing::Environment类

相关推荐
labuladuo5207 分钟前
AtCoder Beginner Contest 372 F题(dp)
c++·算法·动态规划
DieSnowK10 分钟前
[C++][第三方库][httplib]详细讲解
服务器·开发语言·c++·http·第三方库·新手向·httplib
StrokeAce2 小时前
linux桌面软件(wps)内嵌到主窗口后的关闭问题
linux·c++·qt·wps·窗口内嵌
家有狸花5 小时前
VSCODE驯服日记(三):配置C++环境
c++·ide·vscode
dengqingrui1236 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝6 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O6 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
小飞猪Jay9 小时前
C++面试速通宝典——13
jvm·c++·面试
rjszcb9 小时前
一文说完c++全部基础知识,IO流(二)
c++