0%

GTEST

基本使用

安装

Hello World

TODO

断言

gtest中,断言的宏根据作用效果可以理解为分为两类:

  • ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)。
  • _EXPECT_* 系列的断言,当检查点失败时,继续往下执行。

根据作用区分,可以分为几大类

  • 数值类型数据检查:ASSERT_EQ(expected, actual)

  • 布尔值检查:ASSERT_TRUE(condition)

  • 字符串检查:ASSERT_STREQ(str1,str2)

  • 异常检查:ASSERT_THROW(statement, exception_type)

  • 浮点型检查:ASSERT_NEAR(val1, val2, abs_error)

  • 类型检查

  • …….

GTEST中包含非常丰富的断言,这里不赘述,详细内容请参考Assertions Reference | GoogleTest

如果你对自动输出的出错信息不满意的话,你还可以通过操作符<<将一些自定义的信息输出,通常,这对于调试或是对一些检查点的补充说明来说,非常有用!

EXPECT_EQ(x[i], y[i]) << “Vectors x and y differ at index “ << i;

事件

gtest提供了多种事件机制,非常方便我们在案例之前或之后做一些操作。

全局事件

全局的时间在所有案例前后执行。要实现全局事件,必须写一个类,继承testing::Environment类,实现里面的SetUpTearDown方法。

  1. SetUp()方法在所有案例执行前执行

  2. TearDown()方法在所有案例执行后执行

我们还需要告诉gtest添加这个全局事件,我们需要在main函数中通过testing::AddGlobalTestEnvironment方法将事件挂进来,也就是说,我们可以写很多个这样的类,然后将他们的事件都挂上去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
    }
};
int main(int argc, _TCHAR* argv[])
{
    testing::AddGlobalTestEnvironment(new FooEnvironment);
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

TestSuite事件

我们需要写一个类,继承testing::Test,然后实现SetUpTestCase()TearDownTestCase()两个静态方法。在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class FooTest : public testing::Test {
 protected:
  static void SetUpTestCase() {
    shared_resource_ = new ;
  }
  static void TearDownTestCase() {
    delete shared_resource_;
    shared_resource_ = NULL;
  }
  // Some expensive resource shared by all tests.
  static T* shared_resource_;
};
TEST_F(FooTest, Test1)
 {
    // you can refer to shared_resource here 
}
TEST_F(FooTest, Test2)
 {
    // you can refer to shared_resource here 
}

TestCase事件

TestCase事件是挂在每个案例执行前后的,实现方式和上面的几乎一样,不过需要实现的是SetUp方法和TearDown方法。

参数化

在设计测试案例时,经常需要考虑给被测函数传入不同的值的情况,GTEST提供了一个灵活的参数化测试的方案。如果我们测试一个素数检查函数bool isPrime(int ),我们需要进行以下的步骤:

  1. 添加一个类,继承testing::TestWithParam<T>,其中T就是你需要参数化的参数类型,比如上面的例子,需要参数化一个int型的参数。
  2. 告诉gtest拿到参数的值后,具体做些什么样的测试。我们需要引入一个新的宏TEST_P,关于这个”P”的含义,可以理解为”parameterized” 或者 “pattern”。
  3. 告诉gtest你想要测试的参数范围是什么,然后使用INSTANTIATE_TEST_CASE_P宏来告诉gtest你要测试的参数范围。
1
INSTANTIATE_TEST_CASE_P(TrueReturn, IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17));
  • 第一个参数是测试案例的前缀,可以任意取。

  • 第二个参数是测试案例的名称,需要和之前定义的参数化的类的名称相同,

  • 第三个参数是可以理解为参数生成器,上面的例子使用test::Values表示使用括号内的参数。Google提供了一系列的参数生成的函数:

    函数 解释
    Range(begin, end[, step]) 范围在begin~end之间,步长为step,不包括end
    Values(v1, v2, …, vN) v1,v2到vN的值
    ValuesIn(container) and ValuesIn(begin,end) 从一个C类型的数组或是STL容器,或是迭代器中取值
    Bool() 取false 和 true 两个值
    Combine(g1, g2, …, gN) 它将g1,g2,…gN进行排列组合,g1,g2,…gN本身是一个参数生成器,每次分别从g1,g2,..gN中各取出一个值,组合成一个元组(Tuple)作为一个参数

综上所述,我们可以完成对素数检查函数的测试:

1
2
3
4
5
6
7
8
9
10
class IsPrimeParamTest : public::testing::TestWithParam<int>
{

};
TEST_P(IsPrimeParamTest, HandleTrueReturn)
{
int n = GetParam();
EXPECT_TRUE(IsPrime(n));
}
INSTANTIATE_TEST_CASE_P(TrueReturn, IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17));

gtest还提供了应付各种不同类型的数据时的方案,以及参数化类型的方案。这里不详细展开。

参数列表

命令行参数 说明
–gtest_list_tests 使用这个参数时,将不会执行里面的测试案例,而是输出一个案例的列表。
–gtest_filter 对执行的测试案例进行过滤,支持通配符
–gtest_also_run_disabled_tests 执行案例时,同时也执行被置为无效的测试案例。
–gtest_repeat=[COUNT] 设置案例重复运行次数

执行案例时,同时也执行被置为无效的测试案例。关于设置测试案例无效的方法为:

在测试案例名称或测试名称中添加DISABLED前缀,比如:

1
2
3
4
5
6
>TEST(FooTest, DISABLED_DoesAbc) {  }

>class DISABLED_BarTest : public testing::Test {  };


>TEST_F(DISABLED_BarTest, DoesXyz) {  }

[玩转Google开源C++单元测试框架Google Test系列(gtest)之一 - 初识gtest - CoderZh - 博客园 (cnblogs.com)](https://www.cnblogs.com/coderzh/archive/2009/04/06/1426758.html