Gtest:事件
前言
有时候在测试的时候,我们会在测试前做一些初始化活动,和测试后做一些清理工作,gtest提供了多种事件机制,非常方便我们在案例之前或之后做一些操作。总结一下gtest的事件一共有3种:
- 全局的,所有案例执行前后。
- TestSuite级别的,在某一批案例中第一个案例前,最后一个案例执行后。
- TestCase级别的,每个TestCase前后。
接下来按照倒叙3→2→1介绍如何使用事件机制
TestCase事件
TestCase事件是挂在每个案例执行前后的,实现方式和上面的几乎一样,不过需要实现的是SetUp方法和TearDown方法:
1. SetUp()方法在每个TestCase之前执行
2. TearDown()方法在每个TestCase之后执行
演示代码(Linux环境)
main.cpp

#include "sample-inl.h" #include "gtest/gtest.h" namespace { class QueueTestSmpl : public testing::Test { protected: virtual void SetUp() { //q0_.Enqueue(1); q1_.Enqueue(1); q1_.Enqueue(2); q2_.Enqueue(3); } virtual void TearDown() { } static int Double(int n) { return 2 * n; } // A helper function for testing Queue::Map(). void MapTester(const Queue<int> * q) { // Creates a new queue, where each element is twice as big as the // corresponding one in q. const Queue<int> * const new_q = q->Map(Double); // Verifies that the new queue has the same size as q. ASSERT_EQ(q->Size(), new_q->Size()); // Verifies the relationship between the elements of the two queues. for (const QueueNode<int>*n1 = q->Head(), *n2 = new_q->Head(); n1 != nullptr; n1 = n1->next(), n2 = n2->next()) { EXPECT_EQ(2 * n1->element(), n2->element()); } delete new_q; } // Declares the variables your tests want to use. Queue<int> q0_; Queue<int> q1_; Queue<int> q2_; }; // Tests Dequeue(). TEST_F(QueueTestSmpl, Dequeue) { int * n = q0_.Dequeue(); EXPECT_TRUE(n == nullptr); n = q1_.Dequeue(); ASSERT_TRUE(n != nullptr); EXPECT_EQ(1, *n); EXPECT_EQ(1u, q1_.Size()); delete n; n = q1_.Dequeue(); ASSERT_TRUE(n != nullptr); EXPECT_EQ(2, *n); EXPECT_EQ(0u, q1_.Size()); delete n; n = q2_.Dequeue(); ASSERT_TRUE(n != nullptr); EXPECT_EQ(3, *n); EXPECT_EQ(0u, q2_.Size()); delete n; } } // namespace
sample-inl.h

#ifndef GTEST_SAMPLES_SAMPLE_INL_H_ #define GTEST_SAMPLES_SAMPLE_INL_H_ #include <stddef.h> template <typename E> // E is the element type class Queue; template <typename E> // E is the element type class QueueNode { friend class Queue<E>; public: // Gets the element in this node. const E& element() const { return element_; } // Gets the next node in the queue. QueueNode* next() { return next_; } const QueueNode* next() const { return next_; } private: // Creates a node with a given element value. The next pointer is // set to NULL. explicit QueueNode(const E& an_element) : element_(an_element), next_(nullptr) {} // We disable the default assignment operator and copy c'tor. const QueueNode& operator = (const QueueNode&); QueueNode(const QueueNode&); E element_; QueueNode* next_; }; template <typename E> // E is the element type. class Queue { public: // Creates an empty queue. Queue() : head_(nullptr), last_(nullptr), size_(0) {} // D'tor. Clears the queue. ~Queue() { Clear(); } // Clears the queue. void Clear() { if (size_ > 0) { // 1. Deletes every node. QueueNode<E>* node = head_; QueueNode<E>* next = node->next(); for (; ;) { delete node; node = next; if (node == nullptr) break; next = node->next(); } // 2. Resets the member variables. head_ = last_ = nullptr; size_ = 0; } } size_t Size() const { return size_; } QueueNode<E>* Head() { return head_; } const QueueNode<E>* Head() const { return head_; } QueueNode<E>* Last() { return last_; } const QueueNode<E>* Last() const { return last_; } void Enqueue(const E& element) { QueueNode<E>* new_node = new QueueNode<E>(element); if (size_ == 0) { head_ = last_ = new_node; size_ = 1; } else { last_->next_ = new_node; last_ = new_node; size_++; } } E* Dequeue() { if (size_ == 0) { return nullptr; } const QueueNode<E>* const old_head = head_; head_ = head_->next_; size_--; if (size_ == 0) { last_ = nullptr; } E* element = new E(old_head->element()); delete old_head; return element; } template <typename F> Queue* Map(F function) const { Queue* new_queue = new Queue(); for (const QueueNode<E>* node = head_; node != nullptr; node = node->next_) { new_queue->Enqueue(function(node->element())); } return new_queue; } private: QueueNode<E>* head_; // The first node of the queue. QueueNode<E>* last_; // The last node of the queue. size_t size_; // The number of elements in the queue. // We disallow copying a queue. Queue(const Queue&); const Queue& operator = (const Queue&); }; #endif // GTEST_SAMPLES_SAMPLE3_INL_H_
TestSuite事件
这个相对来说比较简单,相对上面的实现就是替换成静态的SetUpTestCase,代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class FooTest : public testing::Test { protected : //准备资源 static void SetUpTestCase() { shared_resource_ = new ; } //释放资源 static void TearDownTestCase() { delete shared_resource_; shared_resource_ = NULL; } // 资源 static T* shared_resource_; }; |
全局事件
也是很简单的,就是继承于testing::Environment而已。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class FooEnvironment: public testing::Environment { public : virtual void SetUp() { printf ( "Environment SetUp!\n" ); a = 100; } virtual void TearDown() { printf ( "Environment TearDown!\n" ); } int a; //共享数据 }; FooEnvironment* foo_env; //对象指针声明 TEST(firstTest, first) //访问共享数据并改变它的值 { printf ( "in the firstTest, foo_env->p is %d\n" , foo_env->a); foo_env->a ++; } TEST(secondTest, second) //访问共享数据 { printf ( "in the secondTest, foo_env->p is %d\n" , foo_env->a); } int main( int argc, char * argv[]) { foo_env = new FooEnvironment; testing::AddGlobalTestEnvironment(foo_env); //注册 testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决