gtest 事件机制:是指在测试前和测试后提供给客户自行添加操作的机制,而且此机制也可以让同一测试套件下的测试用例共享数据。
gtest的事件机制一共有三种:
在讲解事件机制之前,先说明:1、gtest可以脱离main函数执行。
2、如果必须使用main函数,main函数要放到命名空间外面
3、启动测试时所有使用TEST宏、TEST_F宏、TEST_P宏的测试案例都会被执行。
一、全局事件机制(针对整个测试程序)
实现全局的事件机制,需要创建一个自己的类,然后继承testing::Environment类,然后分别实现成员函数SetUp()和TearDown(),同时在main函数内进行调用,即添加以下代码:“testing::AddGlobalTestEnvironment(new MyEnvironment);”,通过调用函数我们可以添加多个全局的事件机制。
实例代码如下(以下所有示例代码运行在VS2022中):
#include "gtest/gtest.h"
/* 两数相加函数实现 */
int add(int a,int b)
{
return (a + b);
}
/* 创建类 继承testing::Environment */
class Client:public testing::Environment {
public:
void SetUp()
{
std::cout << "全局的事件机制(针对整个测试程序) SetUp " << std::endl;
};
void TearDown()
{
std::cout << "全局的事件机制(针对整个测试程序) TearDown " << std::endl;
};
};
/* 测试用例1 */
TEST(IsAddTest, HandlerTrueReturn1) {
EXPECT_EQ(3, add(2, 1));
}
/* 测试用例2 */
TEST(IsAbsTest, HandlerTrueReturn2)
{
EXPECT_TRUE(Abs(1) == 1) << "Abs(1) 期望等于 1"; //ASSERT_TRUE期待结果是true,operator<<输出一些自定义的信息
EXPECT_TRUE(Abs(-1) == 1) << "Abs(-1)=1";
/* 主函数 */
int main(int argc, char* argv[]) {
testing::AddGlobalTestEnvironment(new Client);
testing::InitGoogleTest(&argc, argv);//将命令行参数传递给gtest
return RUN_ALL_TESTS(); //RUN_ALL_TESTS()运行所有测试案例
};
运行结果如下: SetUp()函数是在所有测试开始前执行,TearDown()函数是在所有测试结束后执行
如果修改test case名称为类名称:Client,运行不会报错,代码改动部分如下:
TEST(**Client**, HandlerTrueReturn1) {
EXPECT_EQ(3, add(2, 1));
}
TEST(**Client**, HandlerTrueReturn2)
{
EXPECT_TRUE(Abs(1) == 1) << "Abs(1) 期望等于 1"; //ASSERT_TRUE期待结果是true,operator<<输出一些自定义的信息
EXPECT_TRUE(Abs(-1) == 1) << "Abs(-1)=1";
/*下面这条断言失败,接下来的断言不会再被执*/
运行结果如下:
二、局部的事件机制(针对一个个测试套件,TestSuite事件)
测试套件的事件机制我们同样需要去创建一个类,继承testing::Test,实现两个静态(static)函数SetUpTestCase()和TearDownTestCase(),测试套件的事件机制不需要像全局事件机制一样在main注册,而是需要将我们平时使用的TEST宏改为TEST_F宏。
SetUpTestCase()函数是在测试套件第一个测试用例开始前执行。
TearDownTestCase()函数是在测试套件最后一个测试用例结束后执行。
注:TEST_F的第一个参数使我们创建的类名,也就是当前测试套件的名称。
多个测试场景需要相同数据配置的情况,用TEST_F
示例代码如下:
#include "gtest/gtest.h"
#include <iostream>
using namespace std;
/*
TestSuite事件
需要写一个类,继承testing::Test,然后实现两个**静态**方法:
SetUpTestCase方法在第一个TestCase之前执行;TearDownTestCase方法在最后一个TestCase之后执行。
*/
class jj :public testing::Test
{
public:
/* **必须要加static 否则TEST_P会报错** */
static void SetUpTestCase()
{
std::cout << "局部事件机制,针对TestSuite事件 good good study" << std::endl;
}
static void TearDownTestCase()
{
std::cout << "局部事件机制,针对TestSuite事件 day day up" << std::endl;
}
};
int add_number(int a, int b) {
return (a + b);
}
int reduce_number(int a, int b) {
return (a - b);
}
TEST_F(jj,add_num) { //此时使用的是TEST_F宏,test case名称都为类名:jj
EXPECT_EQ(3, add_number(1, 2));
std::cout << "add_num ASSERT SUCCEED!" << std::endl;
}
TEST_F(jj, reduce_num) {
EXPECT_EQ(2, reduce_number(3, 1));
std::cout << "reduce_num ASSERT SUCCEED!" << std::endl;
}
运行结果如下:
异常情况:
class gyy:public testing::Test {
public:
static void SetUpTestCase() {
std::cout << "局部事件机制 TearDownTestCase " << std::endl;
}
static void TearDownTestCase() {
std::cout << "局部事件机制 TearDownTestCase " << std::endl;
}
};
/*
第一个参数是 测试用例名,第二个参数是 测试用例中某项测试的名称。
一个测试用例可以包含任意数量的独立测试。这两个参数组成了一个测试的全称
*/
TEST(gyy, TestName0) {
EXPECT_EQ(1, add(0,1));
EXPECT_TRUE(add(1, 0))<<"故意出的错误";
EXPECT_EQ(10, add(5, 5));
EXPECT_EQ(100, add(50, 50));
}
TEST_F(gyy, TestName1) {
EXPECT_EQ(2,add(1, 1));
}
运行结果:
三、个体的事件机制(针对一个个测试用例)
测试用例的事件机制的创建和测试套件的基本一样,不同地方在于测试用例实现的两个函数分别是SetUp()和TearDown(),这两个函数不是静态函数。
SetUp()函数是在一个测试用例的开始前执行。TearDown()函数是在一个测试用例的结束后执行。
示例代码如下:
#include "gtest/gtest.h"
#include <iostream>
using namespace std;
class TestMap :public testing::Test
{
public:
//加了Virtual关键字的函数就是虚拟函数,在基类的派生类中就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。
virtual void SetUp() //TEST跑之前会执行SetUp
{
cout << "我是每个方法之前都会执行的SetUp" << endl;
test_map.insert(make_pair(1, 0));
test_map.insert(make_pair(2, 1));
test_map.insert(make_pair(3, 2));
test_map.insert(make_pair(4, 3));
test_map.insert(make_pair(5, 4));
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
cout << "我是每个方法之后都会执行的TearDown" << endl;
test_map.clear();
}
map<int, int> test_map;
};
TEST_F(TestMap, Find) //此时使用的是TEST_F宏
{
map<int, int>::iterator it = test_map.find(1);
ASSERT_NE(it, test_map.end());
cout << "find函数断言成功" << endl;
}
TEST_F(TestMap, Size)
{
ASSERT_EQ(test_map.size(), 5)<<"字典大小等于5";
cout << "Size函数断言成功" << endl;
}
执行结果如下:
TEST_F与TEST的区别是,TEST_F提供了一个初始化函数(SetUp)和一个清理函数(TearDown),在TEST_F中使用的变量可以在初始化函数SetUp中初始化,在TearDown中销毁,并且所有的TEST_F是互相独立的,都是在初始化以后的状态开始运行,一个TEST_F不会影响另一个TEST_F所使用的数据
总结如下:
**
- 在同一份TestCase中不能同时出现TEST和TEST_F两者进行混用;
- 局部事件机制、个体事件机制 继承类testing::Test,使用TEST_F宏
- 全局事件机制继承继承类testing::Environment**,同时在main函数内进行调用,即添加以下代码:testing::AddGlobalTestEnvironment(new MyEnvironment); 和使用哪种宏无关
**