上文(C++开发测试工具gmock的安装与使用超详解)介绍了gmock的安装、配置与基本使用案例,本文将详细介绍一下gmock的基本语法,结合上文一起食用效果更佳哦~
一、简单Demo
首先来编写一个简单Demo,编写代码之前,首先需要将解决方案的平台与目标程序一致,这里选择的是x64,然后版本也要与目标程序一致,这里选择的是release版本。
新建一个头文件,命名为demo.h,声明一个类Foo,内部定义一个公共函数Fun,代码如下:
#pragma once
class Foo
{
public:
virtual int Fun(int i, int j);
};
在demo.cpp中实现该函数功能:
#include"demo.h"
int Foo::Fun(int i, int j)
{
return i + j;
}
新建一个测试文件,命名为demo_test.cpp,代码如下:
#include "gmock\gmock.h"
#include"gtest\gtest.h"
#include"demo.h"
using namespace testing;
TEST(DemoTest,Fun)
{
Foo f;
EXPECT_EQ(3, f.Fun(1, 2));
}
int main(int argc, char** argv)
{
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
这里有两个宏TEST和EXPECT_EQ, TEST这个宏,它有两个参数,这两个参数的解释为:[TestSuiteName,TestCaseName]。
运行结果:
相关含义已经在上文介绍过了,本文不再进行重点介绍。
二、断言
2.1 ASSERT和EXPECT
在gmock/gtest中,断言的宏可以理解为分为两类,一类是ASSERT系列,一类是EXPECT系列。
一个直观的解释就是:
- ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例);
- EXPECT_* 系列的断言,当检查点失败时,继续往下执行;
常用的断言如下:
ASSERT宏 | EXPECT宏 | 功能 |
---|---|---|
ASSERT_TRUE | EXPECT_TRUE | 判真 |
ASSERT_FALSE | EXPECT_FALSE | 判假 |
ASSERT_EQ | ASSERT_EQ | 相等 |
… | … | … |
2.2 流
所有ASSERTION宏都支持使用运算符(如<<)将自定义失败信息传输到其中。例如将代码进行修改:
修改1(故意错误):
EXPECT_EQ(4, f.Fun(1, 2));
修改2(故意错误且利用流输出失败信息):
EXPECT_EQ(3, f.Fun(1, 2))<<"This is a failure message--"<<f.Fun(1,2);
二者的运行结果分别如下图左和右所示:
修改3(运行正常):
EXPECT_EQ(3, f.Fun(1, 2))<<"This is a failure message--"<<f.Fun(1,2);
运行结果如图一所示,没有错误且没有输出任何信息,这说明流<<只能将失败信息传输出来。
三、测试TEST()
测试宏语法如下:
TEST(TestSuiteName,TestName){
//test body
}
TEST()参数从一般到具体。
第一个参数是测试套件(test suite)的名称;
第二个参数是测试套件(test suite)中的测试名称;
这两个名称都必须是有效的C++标识符,并且不应包含任何下划线(_)。
测试的全名由其包含的测试套件及其测试名称组成。来自不同的测试套件的测试可以具有相同的测试名称。
示例如下:
int Factorial(int n); // Returns the factorial of n
这个函数的测试套件可能是这样的:
// Tests factorial of 0.
TEST(FactorialTest, HandlesZeroInput) {
EXPECT_EQ(Factorial(0), 1);
}
// Tests factorial of positive numbers.
TEST(FactorialTest, HandlesPositiveInput) {
EXPECT_EQ(Factorial(1), 1);
EXPECT_EQ(Factorial(2), 2);
EXPECT_EQ(Factorial(3), 6);
EXPECT_EQ(Factorial(8), 40320);
}
googletest按测试套件对测试结果进行分组,因此逻辑相关的测试应位于同一测试套件中;换句话说,他们的第一个参数应该是相同的。在上面的示例中,我们有两个测试HandlesZerosInput和HandlesPositiveInput,它们属于同一个测试套件FactorialTest。
对于第一小节(简单Demo)的示例,在RUN的右侧利用TestSuite.TestName表示:
四、调用测试和main()
定义测试TEST()后,可以使用**RUN_ALL_TESTS()**运行它们,如果所有测试都成功,则返回0,否则返回1。请注意在链接单元中运行所有测试,它们可以来自不同测试套件(test suite),甚至可以来自不同的源文件。
调用该宏(RUN_ALL_TESTS)时:
- 保存所有googletest的标志状态;
- 为第一个测试创建一个测试夹具(test fixture);
- 由SetUp()进行初始化;
- 在fixture对象上运行测试;
- 通过TearDown()清理fixture;
- 删除fixture;
- 恢复所有googletest的状态;
- 对下一个测试重复上述步骤,指导所有测试都已运行。
【注意】:不能忽略RUN_ALL_TESTS()的返回值。此设计的基本原理是:自动测试服务根据其退出代码确定测试是否通过。即在main()函数最后需要return该值,因此核心代码为:
int main(int argc, char** argv)
{
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
在调用RUN_ALL_TESTS()之前必须要调用testing::InitGoogleTest()函数,否则flags将无法正确初始化。
主函数:
大多数用户不需要编写自己的函数,而是链接到main()。