GTest & GMock
ASSERT_ & EXPECT_
Bool
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_TRUE(condition); | EXPECT_TRUE(condition); | condition is true |
ASSERT_FALSE(condition); | EXPECT_FALSE(condition); | condition is false |
Value
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 |
string
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 contents |
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 contents, ignoring case |
注意:“CASE”表明忽略大小写,一个 NULL 指针和空字符串不一样
TEST
下面以 googletest/samples 中的 sample1_unittest.cc 中的 demo 为例,简单介绍下一个简单计算阶乘函数 Factorial 实现如下:
1 | int Factorial(int n) { |
用法如下:
1 | // 下面三个 TEST 都是属于同一个 test suite,即 FactorialTest |
在 sample1_unittest.cc 的 main 函数中,添加 RUN_ALL_TESTS 函数即可。
1 | int main(int argc, char **argv) { |
在 TEST 宏函数中,也可以像个普通函数一样,定义变量之类的行为。
比如在 sample2_unittest.cc 中,测试一个自定义类 MyString 的复制构造函数是否表现正常:
1 | const char kHelloString[] = "Hello, world!"; |
TEST_F
下面介绍 gtest 中更为高级的功能:test fixture,对应的宏函数是 TEST_F(TestFixtureName, TestName)。
fixture,其语义是固定的设施,而 test fixture 在 gtest 中的作用就是为每个 TEST 都执行一些同样的操作。
比如,要测试一个队列 Queue 的各个接口功能是否正常,因此就需要向队列中添加元素。如果使用一个 TEST 函数测试 Queue 的一个接口,那么每次执行 TEST 时,都需要在 TEST 宏函数中定义一个 Queue 对象,并向该对象中添加元素,就很冗余、繁琐。
怎么避免这部分冗余的过程?
TEST_F 就是完成这样的事情,它的第一个参数 TestFixtureName 是个类,需要继承 testing::Test,同时根据需要实现以下两个虚函数:
- virtual void SetUp():在 TEST_F 中测试案例之前运行;
- virtual void TearDown():在 TEST_F 之后运行。
可以类比对象的构造函数和析构函数。这样,同一个 TestFixtureName 下的每个 TEST_F 都会先执行 SetUp,最后执行 TearDwom。
此外,testing::Test 还提供了两个 static 函数:
- static void SetUpTestSuite():在第一个 TEST 之前运行
- static void TearDownTestSuite():在最后一个 TEST 之后运行
以 sample3-inl 中实现的 class Queue 为例:
1 | class QueueTestSmpl3 : public testing::Test { // 继承了 testing::Test |
下面是 sample3_unittest.cc 中的 TEST_F:
1 | // in sample3_unittest.cc |
以 TEST_F(QueueTestSmpl3, DefaultConstructor) 为例,再具体讲解下 TEST_F 的运行流程:
- gtest 构造一个 QueueTestSmpl3 对象 t1;
- t1.setUp 初始`t1
- 第一个 TEST_F 即 DefaultConstructor 开始运行并结束
- t1.TearDwon 运行,用于清理工作
EXPECT_CALL
1 | EXPECT_CALL(mock_object, method(matcher)) |
- 第一行中 (matcher) 是可有可无的,只有存在函数同名重载的情况下,(matcher) 才是必须的,用于匹配入参格式
- 第二行也是可有可无的,cardinality 表示函数应该被调用的次数。常见的有:Times(n) 应该被调用 n 次;Times(::testing::AtLeast(n)) 至少应该被调用 n 次
- 第三行和第四行,表示做一次或重复做 action。常见的 action 有::testing::Return(n) 表示返回一个数字
例如:
1 | EXPECT_CALL(mock_if_impl, some_func) |