GTest基础学习-05-第5个单元测试-父test fixture和子test fixture的使用

这篇来学习Gtest官方示例中的第5个,为什么直接跳过第4个,因为第四个是测试一个简单的计数器,看了下单元测试内容,没有新的知识点,就一个TEST,里面使用了连续3 4个EXPECT_TRUE断言宏。完全没有任何新的知识点,就不再介绍第4个例子,直接来看第五个。第五个是介绍test fixture可以通过继承使用父类中的测试夹具。

 

1.场景

这个例子教我们如何在多个测试用例中复用测试夹具:通过派生子夹具。当你定义好了一个测试夹具,你指定一个测试用例使用这个测试夹具。一个测试夹具只能被一个测试用例使用。某些时候,更多的测试用例希望使用相同或有一点不同的测试夹具。例如,你可能想要确保GUI库的所有测试都不会泄漏系统资源,例如字体和画笔。在Gtest中,你可以这样做,把共享逻辑放入一个超类的测试夹具中。每个测试用例使用到的测试夹具从这个超类中派生。

 

不同的测试用例如果是共同的数据和逻辑,直接从父类继承就好,如果有需要不同的,可以通过重写父类的SetUp()或者TearDown()方法。

 

2.第5个示例

第五个示例没有单独的头文件和实现文件,测试文件都是测试sample01和sample03中的内容。

TestSample05.cpp

#include 
#include 
#include "gtest/gtest.h"
#include "sample01.h"
#include "sample03.h"
namespace {
	// 在这次示例中, 我们要确保每个测试必须在5秒内结束
	//如果有超过5秒,我们把这个测试判为失败
	//
	// 我们把在测试夹具中计算代码运行时间叫做"QuickTest".  QuickTest 被设计为一个超夹具类,这样其他夹具可以从这个类派生.
	//
	// 之后,我们将从QuickTest派生多个测试夹具类
	class QuickTest : public testing::Test {
	protected:
		// 提醒一下:SetUp() 是在一个test执行之前就会执行
		// 这是一个好地方去记录开始时间
		void SetUp() override { start_time_ = time(nullptr); }

		// TearDown() 是在每个测试执行结束之后才会被执行. 
		// 这里我们检查下这个测试是不是运行太慢(大于5秒)
		void TearDown() override {
			// 当测试结束获取结束时间
			const time_t end_time = time(nullptr);

			// 断言测试运行没有超过5秒.  Did you
			// 你是否知道在 SetUp() 和TearDown()也可以使用测试断言
			EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
		}

		// UTC 时间(秒为单位)
		time_t start_time_;
	};


	// 我们从QuickTest类派生一个夹具叫IntegerFunctionTest
	// 使用此夹具的所有测试将自动进行quick test
	class IntegerFunctionTest : public QuickTest {
		// 这里我们不再需要更多的逻辑,直接继承来自父类QuickTest 的测试夹具
		// 因此,这个类的是一个空的
	};


	// 现在我们可以写测试用例,用夹具:IntegerFunctionTest 

	// 测试阶乘
	TEST_F(IntegerFunctionTest, Factorial) {
		// 测试负数的阶乘
		EXPECT_EQ(1, Factorial(-5));
		EXPECT_EQ(1, Factorial(-1));
		EXPECT_GT(Factorial(-10), 0);

		// 测试0的阶乘
		EXPECT_EQ(1, Factorial(0));

		// 测试正整数的阶乘
		EXPECT_EQ(1, Factorial(1));
		EXPECT_EQ(2, Factorial(2));
		EXPECT_EQ(6, Factorial(3));
		EXPECT_EQ(40320, Factorial(8));
	}


	// 测试是否为素数
	TEST_F(IntegerFunctionTest, IsPrime) {
		// 测试负数是否为素数
		EXPECT_FALSE(IsPrime(-1));
		EXPECT_FALSE(IsPrime(-2));
		EXPECT_FALSE(IsPrime(INT_MIN));

		// 测试几个简单的数字是否为素数
		EXPECT_FALSE(IsPrime(0));
		EXPECT_FALSE(IsPrime(1));
		EXPECT_TRUE(IsPrime(2));
		EXPECT_TRUE(IsPrime(3));

		// 测试正整数是否为素数
		EXPECT_FALSE(IsPrime(4));
		EXPECT_TRUE(IsPrime(5));
		EXPECT_FALSE(IsPrime(6));
		EXPECT_TRUE(IsPrime(23));
	}


	// 下一个测试用例 (叫 "QueueTest") 也需要更快执行完成, so
	// 所以我们这里也从QuickTest.派生另外一个测试夹具
	//
	// QueueTest的测试夹具已经可以继承来自父类的测试夹具.  
	// 通常,如果还有不同,我们这里定义下额外的,所以需要重写父类的SetUp方法
	class QueueTest : public QuickTest {
	protected:
		void SetUp() override {
			// 第一个需要初始化一下父类 (QuickTest)中的SetUp()
			QuickTest::SetUp();

			// 第二, 一些额外的初始化操作.
			q1_.Enqueue(1);
			q2_.Enqueue(2);
			q2_.Enqueue(3);
		}

		// 默认TearDown()的行为继承来自QuickTest::TearDown()
		// 这里我们没有额外的清除操作,在QueueTest我们把TearDown()代码给注销
		//
		// virtual void TearDown() {
		//   QuickTest::TearDown();
		// }

		Queue q0_;
		Queue q1_;
		Queue q2_;
	};


	//现在让我们用 QueueTest 的测试夹具来写测试

	// 测试默认的构造
	TEST_F(QueueTest, DefaultConstructor) {
		EXPECT_EQ(0u, q0_.Size());
	}

	// 测试队列新增元素
	TEST_F(QueueTest, Dequeue) {
		int* n = q0_.Dequeue();
		EXPECT_TRUE(n == nullptr);

		n = q1_.Dequeue();
		EXPECT_TRUE(n != nullptr);
		EXPECT_EQ(1, *n);
		EXPECT_EQ(0u, q1_.Size());
		delete n;

		n = q2_.Dequeue();
		EXPECT_TRUE(n != nullptr);
		EXPECT_EQ(2, *n);
		EXPECT_EQ(1u, q2_.Size());
		delete n;
	}
}  // namespace
   //如果有必要,你可以派生更多的测试夹具,例如,你可以从 QueueTest派生另外一个夹具
   //  Google测试框架对派生层次结构的深度没有限制
  // 但是在实践中,你可能不希望它也是如此,因为容易混淆。

运行结果

GTest基础学习-05-第5个单元测试-父test fixture和子test fixture的使用_第1张图片

 

总结:

如果想多个测试用例使用类似相同的测试夹具,那么可以从一个超类中派生出不同的子测试夹具,通过这些子测试夹具,可以方便测试不同的测试用例。

你可能感兴趣的:(C++单元测试框架Gtest,单元测试,gtest,测试夹具,测试夹具继承)