sample3

sample3展示了如何使用GoogleTest的test fixture。至于将sample3编译出来,则和前面两个sample类似,在CmakeLists.txt添加两行规则即可。

先看sample3_unittest中的说明

一个test fixture是用来存放对象和方法的地方,这些test fixture中存放的对象和方法被所有在test case中的test共享。使用test fixture可以避免重复定义测试必要的初始化和清理代码。也可以被用来定义经常被使用的子程序。

test fixture只是共享代码,而不共享数据。每一个test会得新的到tsst fixture的副本,因此一个test的对数据的修改不会传递给另一test。

这样设计的原因是测试应该是独立的且可重复的。特别是一个测试失败不会导致另一个测试失败。如果一个测试依赖于另一个测试产生的信息,那么这两个test应该属于一个大的test。

用于指示测试成功或失败的宏(EXPECT_TRUE, FAIL, etc),需要知道当前的测试是什么(当Google Test打印测试结果的时候,Google Test会告诉你每一个错误是属于哪一个test)。从技术上来说,这些测试宏是调用test类的一个成员函数,因此不能在全局函数中使用他们,这也是文什么应该在test fixture中定义测试子程序。

sample3-inl.h中的内容

sample3-inl.h 中定义了两个模板类,

template <typename E>
QueueNode
和
template <typename E>
Queue

其中QueueNode类中有两个成员以及三个直接访问这两个成员的方法。除此之外还有节点的几个构造函数。

E element_; //保存队列节点中的元素值。
QueueNode* next_; //保存队列的下一个节点指针。

const E& element(); //获取队列节点值。
QueueNode* next(); 
const QueueNode* next() const; //获取队列的下一个节点指针。

而后是Queue类的内容(Queue类实现了一个队列的功能,而Queue中的每一个节点都是一个QueueNode对象),Queue类有三个成员以及实现一个队列操作所需的一些方法,主要成员和方法如下:

QueueNode<E>* head_; //指向队列的头
QueueNode<E>* least_; //指向队列的尾
size_t size_; //队列的长度

void Clear(); //清空掉队列(依次析构掉每个节点)
size_t Size(); //返回队列的长度
QueueNode<E>* Head(); 
const QueueNode<E>* Head() const; //获得队列的头指针 
QueueNode<E>* Last(); 
const QueueNode<E>* Last() const; //获得队列的尾指针

void Enqueue(const E& element); //入队操作 
E*Dequeue(); //出队操作

templete <typename F>
Queue* Map(F function); //返回一个新的队列,而新队列的每一个元素都是当前队列中的元素经过函数``funciton``转换后的结果。

以上是sample3_unittest.cc中要测试的主要方法,接着看其中的具体测试内容。

sample3_unittest.cc中的内容

sample3中是要教我们如何使用test fixture。
首先定义一个继承自testing::Test的类,而在类中主要可以做以下几种操作。

class QueueTestSmpl3: public testing::test {
protected: //为了让成员能在子类中方法同时使成员受到保护,应该将所有的内容都定义成为protected。
	void SetUp() override { //虚函数``SetUp``会在每一个test开始前被调用,如果需要对成员变量作初始化的话需要定义它。
		q1_.Enqueue(1); 
		q2_.Enqueue(2); 
		q3_.Enqueue(3); 
	};
	void TearDown() override {}; //虚函数``TearDown``则是在每个test结束的时候被调用,因此如果需要作部分清理工作的话可以添加在这里。
	//可以在自定义Test类中定义测试用方法
	static int Double(int n); //函数体不抄了,会返回2*n
	void MapTester(const Queue<int> *q); // 函数体不抄,内容是在测试``Queue``中的``Map``方法是否正确。首先利用q的Map方法(参数为Double方法)构造出另一个Queue对像new_q,而后检测构造出的两个队列长度是否相同,而后逐个比较两者的节点值是否符合预期。
	//接着则是定义了三个``Queue``类型的变量。
	Queue<int> q0_; 
	Queue<int> q1_; 
	Queue<int> q2_; 
};

而后是如何定义每一个Test,当使用test fixture的时候应该使用TEST_F而非使用TEST

TEST_F(QueueTestSmpl3, DefaultConstructor) {
  EXPECT_EQ(0u, q0_.Size());
}

以上使用自定义的test fixture,只是简单的测试使用默认构造函数时的队列长度,不过可以看到在这个test中可以直接访问自定义的test fixture中的成员q0
ps由于类内是protected的,改成public或者private试一下:和预期差不多private报编译错,public则编译出正常可执行文件。
另一个测试:

TEST_F(QueueTestSmpl3, Dequeue) {
  int * n = q0_.Dequeue();
  EXPECT_TRUE(n == nullptr);

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

  n = q2_.Dequeue();
  ASSERT_TRUE(n != nullptr);
  EXPECT_EQ(2, *n);
  EXPECT_EQ(1u, q2_.Size());
  delete n;
}

Dequeue方法进行了测试,没什么新的内容。
最后一个test:

TEST_F(QueueTestSmpl3, Map) {
  MapTester(&q0_);
  MapTester(&q1_);
  MapTester(&q2_);
}

直接调用了自定义的test fixture中的方法对QueueMap方法进行了测试。

总结一下test fixture的使用过程:首先自定义一个类,该类继承自testing::Test。而后类中有两个重要的虚方法需要重载(如果需要的话)void SetUp()void TestDown()其中前个在每个test运行开始前被调用,后一个则是在test运行后被调用。除此之外可以在自定义类内编写对测试对象进行测试的方法,以及提前创建出将要被用于测试的对象。同时注意将以上的东西声明成protected类型(既可以在test中访问到所有东西,也可以隔离起来)。这样便可以在test中访问所定义的成员和方法。不过test case的名字只能是test fixture的名字

test fixture的好处是不用初始化用于测试的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值