gtest学习笔记(四)gtest自带的sample3---Test Fixture减少测试冗余


前言

第一章中已经编译出自带的sample例子,在build/googletest目录下可以看到sample的各种例子的可执行程序。
Google Test 附带了10个单元测试用例,难度由浅及深。
sample3主要演示了Test Fixture的使用(TEST_F宏)。

Fixtures are fittings or furniture which belong to a building and are legally part of it, for example, a bathtub or a toilet. 对于Test Fixture就是每个测试用例执行时都要用到的相同的测试资源,如果对每个测试用例都单独进行编码、用于准备测试资源,代码冗余量太大,因此Test Fixture对于 code sharing意义重大。

使用Test Fixture,需要继承testing::Test类:说白了就是定制化自己的 void SetUp( ) 为测试准备对象.和 virtual void TearDown( )为测试后销毁对象资源,使得不同用例可以使用相同的测试资源及复用相同的代码。

源码学习

  1. sample3由两个部分组成:sample3-inl.h , sample3UnitTest.cpp 。

  2. sample3-inl.h中声明了一个queue队列

#ifndef GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
#define GOOGLETEST_SAMPLES_SAMPLE3_INL_H_

#include <stddef.h>

//此队列是一个单链表
// Queue is a simple queue implemented as a singled-linked list.
// The element type must support copy constructor.
template <typename E>  // E is the element type
class Queue;

// QueueNode是队列中的结点,结点中包含 类型为E的元素 和 指向下一个结点的指针
// QueueNode is a node in a Queue, which consists of an element of
// type E and a pointer to the next node.
template <typename E>  // E is the element type
class QueueNode {
	//Queue是QueueNode的友元类,因此Queue可以访问QueueNode的所有成员
  friend class Queue<E>;

 public:
  // Gets the element in this node.
  // 返回当前结点的元素值(类型E的一个引用)
  const E& element() const { return element_; }
  
  // Gets the next node in the queue.
  为什么出现两个几乎完全一样的 next()呢?
  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;
    }
  }

  // Gets the number of elements.
  size_t Size() const { return size_; }

  // Gets the first element of the queue, or NULL if the queue is empty.
  QueueNode<E>* Head() { return head_; }
  const QueueNode<E>* Head() const { return head_; }

  // Gets the last element of the queue, or NULL if the queue is empty.
  QueueNode<E>* Last() { return last_; }
  const QueueNode<E>* Last() const { return last_; }

  // Adds an element to the end of the queue.  A copy of the element is
  // created using the copy constructor, and then stored in the queue.
  // Changes made to the element in the queue doesn't affect the source
  // object, and vice versa.
  //向队列尾部添加元素,使用拷贝构造,因此该操作不会影响源数据
  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_++;
    }
  }

  // Removes the head of the queue and returns it.  Returns NULL if
  // the queue is empty.
  //删除队列的头元素并返回元素值
  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;
  }

  // Applies a function/functor on each element of the queue, and
  // returns the result in a new queue.  The original queue is not
  // affected.
  //在每一个队列元素上 运用指定函数 function,并将函数结果保存到新队列
  template <typename F>
  Queue* Map(F function) const {
    Queue* new_queue = new Queue();
    for (const QueueNode<E>* node = head_; node != nullptr;
         node = node->next_) {
      //直接void Enqueue(const E &element); 就可以了吧,function多此一举吧?
	  //不是多此一举,在测试文件就可以看到function()的具体使用
      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  // GOOGLETEST_SAMPLES_SAMPLE3_INL_H_

  1. sample3UnitTest.cpp是对应单元测试的代码
#include "sample3-inl.h"
#include "gtest/gtest.h"
namespace {
// To use a test fixture, derive a class from testing::Test.
class QueueTestSmpl3 : public testing::Test {
 protected:  // You should make the members protected s.t. they can be
             // accessed from sub-classes.
  // virtual void SetUp() will be called before each test is run.  You
  // should define it if you need to initialize the variables.
  // Otherwise, this can be skipped.
   // 创建三个 sample03.h中定义的队列
  void SetUp() override {
    //向队列中添加元素
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // virtual void TearDown() will be called after each test is run.
  //Google Test每一条用例执行后都会调用 virtual void TearDown()
  // You should define it if there is cleanup work to do.  Otherwise,
  //TearDown用来清理数据
  // you don't have to provide it.
  //
  // virtual void TearDown() {
  // }

  // A helper function that some test uses.
  static int Double(int n) { return 2 * n; }

  // A helper function for testing Queue::Map().
   //测试类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.
     // 产生了一个新队列,和源队列相比,新队列的每一个元素值都是源队列对应元素值的两倍,这就是function的作用
    const Queue<int>* const new_q = q->Map(Double);

    // Verifies that the new queue has the same size as q.
    //为什么要把单元测试用例写在类的声明中呢? //因为下面的测试用例会调用 见233行
    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_;
};

// When you have a test fixture, you define a test using TEST_F
// instead of TEST.

// Tests the default c'tor.
//1.测试默认的构造函数(每条用例结束,会执行析构函数吗?)
 //注意:测试用例集名字 必须和定义的类名保持一致
TEST_F(QueueTestSmpl3, DefaultConstructor) {
  // You can access data in the test fixture here.
   //这里的结果应该是Pass,因为SetUP()中 q0 未添加数据
  EXPECT_EQ(0u, q0_.Size());
}

// Tests Dequeue().
//2.测试Dequeue()函数
TEST_F(QueueTestSmpl3, Dequeue) {
  int* n = q0_.Dequeue();
  EXPECT_TRUE(n == nullptr);//测试结果Pass,因为SetUP()中 q0_ 未添加元素

  n = q1_.Dequeue();//Dequeue()的返回值是一个E类型的指针
  ASSERT_TRUE(n != nullptr);//pass, SetUP()中 q1 中添加了一个元素
  EXPECT_EQ(1, *n); //q1.Enqueue(1);  pass, 元素值就是1
  EXPECT_EQ(0u, q1_.Size());//弹出一个元素后,队列的元素个数为0;
  delete n;

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

// Tests the Queue::Map() function.
//3.测试Queue::Map()函数(其中包括Enqueue()函数)
TEST_F(QueueTestSmpl3, Map) {
  MapTester(&q0_);//传入的实际是队列的引用
  MapTester(&q1_);
  MapTester(&q2_);
}
}  // namespace

utest语法

  1. TEST_F

运行

通过命令./sample3 运行sample3例子

[==========] Running 3 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 3 tests from QueueTestSmpl3
[ RUN      ] QueueTestSmpl3.DefaultConstructor
[       OK ] QueueTestSmpl3.DefaultConstructor (0 ms)
[ RUN      ] QueueTestSmpl3.Dequeue
[       OK ] QueueTestSmpl3.Dequeue (0 ms)
[ RUN      ] QueueTestSmpl3.Map
[       OK ] QueueTestSmpl3.Map (0 ms)
[----------] 3 tests from QueueTestSmpl3 (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 3 tests.


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值