Gtest之TEST宏的用法

一、TestCase的介绍

Gtest提供了若干个case方法进行测试不同的用例。主要常见的有TEST/TEST_F及TEST_P宏的使用。
在每个TestCase中可以通过断言(Assert)提供的方法,检查程序的走向是否符合期望的结果,从而以此来判定程序的正确性。
在同一份TestCase中不能同时出现TEST和TEST_F两者进行混用;

二、断言

Google Test采用一系列的断言(assertion)来进行代码测试,这些宏有点类似于函数调用。
当断言失败时Google Test将会打印出assertion时的源文件和出错行的位置,以及附加的失败信息,
用户可以直接通过“<<”在这些断言宏后面跟上自己希望在断言命中时的输出信息。
测试宏可以分为两大类:ASSERT_*和EXPECT_*,这些成对的断言功能相同,但效果不同。其中ASSERT_*将会在失败时产生致命错误并中止当前调用它的函数执行。EXPECT_*版本的会生成非致命错误,不会中止当前函数,而是继续执行当前函数。通常情况应该首选使用EXPECT_*,因为ASSERT_*在报告完错误后不会进行清理工作,有可能导致内容泄露问题。

基本断言
Fatal assertion    Nonfatal assertion    Verifies
ASSERT_TRUE(condition);    EXPECT_TRUE(condition);    condition is true
ASSERT_FALSE(condition);    EXPECT_FALSE(condition);    condition is false

二值比较
Fatal assertion    Nonfatal assertion    Verifies
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

字符串比较
Fatal assertion    Nonfatal assertion    Verifies
ASSERT_STREQ(str1,str2);    EXPECT_STREQ(str1,str2);    the two C strings have the same content
ASSERT_STRNE(str1,str2);    EXPECT_STRNE(str1,str2);    the two C strings have different content
ASSERT_STRCASEEQ(str1,str2);    EXPECT_STRCASEEQ(str1,str2);    the two C strings have the same content, ignoring case
ASSERT_STRCASENE(str1,str2);    EXPECT_STRCASENE(str1,str2);    the two C strings have different content, ignoring case
 

三、TEST宏

TEST宏的作用是创建一个简单的测试用例,它定义了一个测试函数,在这个函数里可以使用任何C++代码并使用提供的断言([断言类型介绍])来进行检查。

TEST语法定义:

TEST(test_case_name, test_name)

test_case_name第一个参数是测试用例名,通常是取测试函数名或者测试类名
test_name 第二个参数是测试名这个随便取,但最好取有意义的名称
当测试完成后显示的测试结果将以"测试用例名.测试名"的形式给出
 

#include <gtest/gtest.h>

inline int Add(int i, int j) { return i + j; }

TEST(Add, 负数) {
    EXPECT_EQ(Add(-1, -2), -3);
    EXPECT_GT(Add(-4, -5), -6); // 故意的  
}

TEST(Add, 正数) {
    EXPECT_EQ(Add(1, 2), 3);
    EXPECT_GT(Add(4, 5), 6);
}

int main(int argc, char **argv) {
    std::cout << "Running main() from gtest_main.cc\n";
    testing::InitGoogleTest(&argc, argv);
    RUN_ALL_TESTS();
    system("pause");
    return 0;
}

打印

四、TEST_F宏(Test Fixture)

很多时候,我们想在不同的测试执行前,创建相同的配置环境,在测试执行结束后执行相应的清理工作。测试固件(Test Fixture)为这种需求提供了方便。“Fixture”是一个汉语中不易直接对应的词,《美国传统词典》对它的解释是“(作为附属物的)固定装置;被固定的状态”。

在单元测试中,Fixture的作用是为测试创建辅助性的上下文环境,实现测试的初始化和终结与测试过程本身的分离,便于不同测试使用相同代码来搭建固定的配置环境。测试固件体现了对一系列测试(在开始和结束时)的规定动作。

TEST_F主要是进行多样测试,在多种不同情况的测试TestCase中都会使用相同一份的测试数据的时候将会才用它。即相同的数据测试不同的行为,如果采用TEST宏进行测试那么将会为不同的测试case创建多份数据。TEST_F宏将会共用一份避免重复拷贝共具灵活性。
TEST_F语法定义:

TEST_F(test_case_name, test_name);

test_case_name第一个参数是测试用例名,必须取类名。这个和TEST宏不同
test_name 第二个参数是测试名这个随便取,但最好取有意义的名称
使用TEST_F时必须继承::testing::Test类。并且该类提供了两个接口void SetUp(); void TearDown();

用TES_F比单纯调用 TEST宏稍微麻烦一些:

1、从gtest的 testing::Test类派生一个类,用 public或 protected定义以下所有成员。

2、建立环境:使用默认构造函数,或定义一个虚成员函数 virtual void SetUp()。

3、销毁环境:使用析构函数,或定义一个虚成员函数 virtual void TearDown()。

4、用 TEST_F定义测试,写法与 TEST相同,但测试用例名必须为上面定义的类名。

每个带固件的测试的执行顺序是:

1、调用默认构造函数创建一个新的带固件对象。

2、立即调用 SetUp()。

3、运行 TEST_F体。

4、立即调用 TearDown()。

5、调用析构函数销毁类对象。

inline int Add(int i, int j) { return i + j; }

class AddTest : public testing::Test
{
public:
    virtual void SetUp() { puts("SetUp()"); }
    virtual void TearDown() { puts("TearDown()"); }
};

TEST_F(AddTest, 正数) {
    ASSERT_GT(Add(1, 2), 3); // 故意的  
    ASSERT_EQ(Add(4, 5), 6); // 也是故意的  
}

TEST_F(AddTest, 复数) {
    ASSERT_GT(Add(2, 2), 3); // 故意的  
    ASSERT_EQ(Add(8, 5), 6); // 也是故意的  
}

int main(int argc, char **argv) {
    std::cout << "Running main() from gtest_main.cc\n";
    testing::InitGoogleTest(&argc, argv);
    RUN_ALL_TESTS();
    system("pause");
    return 0;
}

 

五、TEST_P

当待测试方法的行为取决于传入的参数时,而且这些参数的不同组合有多种, 而你又不想为此写多个相类似的test case时,可以用value-parameterized Test

value-parameterized Test 允许你可以使用不同的参数测试代码, 而无需编写同一测试的多个副本

enum class CalculateType : int
{
    add = 1,
    minus = 2,
    plus = 3,
    divide = 4
};

class MyClass
{
public:
    int calculate(int a, int b, CalculateType type)
    {
        int c = 0;
        switch (type)
        {
        case CalculateType::add:
            c = a + b;
            break;
        case CalculateType::minus:
            c = a - b;
            break;
        case CalculateType::plus:
            c = a * b;
            break;
        case CalculateType::divide:
            c = a / b;
            break;
        }
        return c;
    }
};
struct MyTestData
{
    int a;
    int b;
    CalculateType type;
};


class TestMyClass : public ::testing::Test,
    public ::testing::WithParamInterface<MyTestData>
{
public:
    MyClass myclass;
};

TEST_P(TestMyClass, norml)
{
    int a = GetParam().a;
    int b = GetParam().b;
    int re = myclass.calculate(a, b, GetParam().type);
    switch (GetParam().type)
    {
    case CalculateType::add:
        EXPECT_EQ(a + b, re);
        break;
    case CalculateType::minus:
        EXPECT_EQ(a - b, re);
        break;
    case CalculateType::plus:
        EXPECT_EQ(a * b, re);
        break;
    case CalculateType::divide:
        EXPECT_EQ(a / b, re);
        break;
    }
}

INSTANTIATE_TEST_SUITE_P(TestMyClassParams,TestMyClass, ::testing::Values(
        MyTestData{ 1, 2, CalculateType::add },
        MyTestData{ 4, 3, CalculateType::minus },
        MyTestData{ 5, 6, CalculateType::plus },
        MyTestData{ 8, 2, CalculateType::divide }
));

 

 

参考:

Gtest入门2 Gtest之TEST宏的用法_sevencheng798的博客-CSDN博客_gtest test宏

GTest源码剖析(四)——TEST_P宏_沐寒握冰的博客-CSDN博客

gtest和gmock入门_放牛娃不吃草的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值