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)。

编译并执行上述代码,结果如下:

img

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。

编译并执行上述代码,结果如下:

img

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 库。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值