GoogleTest测试框架介绍(二)

本系列文章主要介绍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库。

  • 25
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于Google Test单元测试,你可以在C++项目中使用Google Test框架来编写和运行单元测试。 首先,你需要在项目中包含Google Test库。你可以从Google Test的官方GitHub仓库下载最新版本的源代码,并将其添加到你的项目中。 在编写单元测试之前,你需要创建一个测试文件。这个文件应该包含一个或多个测试用例,每个测试用例都是一个函数。你可以使用Google Test提供的宏来定义和运行测试用例。 一个简单的示例代码如下: ```c++ #include <gtest/gtest.h> // 定义一个测试用例 TEST(ExampleTest, Addition) { int a = 2; int b = 3; int result = a + b; EXPECT_EQ(result, 5); } // 定义另一个测试用例 TEST(ExampleTest, Subtraction) { int a = 5; int b = 3; int result = a - b; EXPECT_EQ(result, 2); } int main(int argc, char** argv) { // 初始化 Google Test 框架 ::testing::InitGoogleTest(&argc, argv); // 运行所有的测试用例 return RUN_ALL_TESTS(); } ``` 在这个例子中,我们定义了两个测试用例:Addition和Subtraction。每个测试用例都包含一些断言,用于验证预期结果和实际结果是否相等。在main函数中,我们初始化Google Test框架并运行所有的测试用例。 要编译和运行这个测试文件,你需要将Google Test库链接到你的项目中。具体的编译和链接过程可能因你使用的开发环境而有所不同。 当你运行这个测试文件时,Google Test将会执行所有的测试用例,并输出测试结果。如果所有的断言都通过了,测试将会被标记为通过;否则,测试将会被标记为失败,并显示详细的错误信息。 这只是一个简单的示例,Google Test还提供了很多其他的功能和特性,例如测试夹具、参数化测试测试报告等。你可以查阅Google Test的官方文档以获取更多信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liitdar

赠人玫瑰,手有余香,君与吾共勉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值