单元测试及gtest学习

1.介绍

单元测试是用来对一个模块、一个函数或者一个来进行正确性检验的测试工作。

  • 为每个单元编写多个测试用例,覆盖不同的输入和输出情况和边界条件(预期什么输入、预期什么输出)
  • 如果需要测试的函数依赖于外部资源(如数据库、网络调用等),可以使用 Mock 或 Stub 对其进行模拟,以隔离测试并确保独立性。
  • 每个测试用例应该是独立的,不依赖于其他测试的结果。确保测试的可重复性,即每次运行测试都应该得到相同的结果。

https://zhuanlan.zhihu.com/p/387540827 

2.gtest

gtest提供的sample:https://google.github.io/googletest/samples.html

用法讲解:https://blog.csdn.net/wangmj_hdu/article/details/118369609

测试中用到的断言与比较函数:https://github.com/AngryHacker/articles/blob/master/src/open_source_components/google_gtest.md

  • 写单测一般包括3个部分,即Given(Mock外部依赖&准备Fake数据),When(调用被测方法)以及Then(断言执行结果)。

3.基础语法学习

//cpp文件中有一个计算阶乘的函数
//sample1.cc
int Factorial(int n) {
  int result = 1;
  for (int i = 1; i <= n; i++) {
    result *= i;
  }

  return result;
}

//对应的单元测试文件
//sample1_unittest.cc
#include "sample1.h"
#include "gtest/gtest.h"
TEST(FactorialTest, Negative) {//宏定义,有2个参数
//第一个参数表示测试case名字,第二个是测试名字。不同的测试被分类到测试组中
  // This test is named "Negative", and belongs to the "FactorialTest"
  // test case.
  EXPECT_EQ(10, Factorial(-5));//也是gtest提供的宏定义
  EXPECT_EQ(1, Factorial(-1));
  EXPECT_GT(Factorial(-10), 0);
}
// Tests factorial of 0.
TEST(FactorialTest, Zero) {
  EXPECT_EQ(1, Factorial(0));
}

int main(int argc, char **argv) {
  printf("Running main() from %s\n", __FILE__);
  //解析命令行中的GoogleTest参数,它允许用户通过多样的命令行参数来控制测试程序的行为(即定制命令行参数的行为)
  testing::InitGoogleTest(&argc, argv);

//将会搜索不同的Test Case和不同的源文件中所有已经存在测试案例,然后运行它们,所有Test都成功时返回1,否则返回0。
  return RUN_ALL_TESTS();
}

GoogleTest根据Test Case(第一个参数)对测试结果进行分组,所以一些相关的Test(第二个参数)应该放在同一个Test Case中。

4.单元测试类

namespace {
// To use a test fixture, derive a class from testing::Test.
class QueueTestSmpl3 : public testing::Test {//继承Test类
 protected:  // You should make the members protected s.t. they can be
             // accessed from sub-classes.
  static void SetUpTestSuite() {//在所有的测试用例开始之前会调用一次
    std::cout<<"run before first case..."<<std::endl;
  } 

  static void TearDownTestSuite() {//在所有测试用例结束之后调用一次
    std::cout<<"run after last case..."<<std::endl;
  }
  // 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.
  virtual void SetUp() override {//每个测试用例执行之前调用一次
    std::cout<<"enter into SetUp()" <<std::endl;
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // virtual void TearDown() will be called after each test is run.
  // You should define it if there is cleanup work to do.  Otherwise,
  // you don't have to provide it.
  //
  virtual void TearDown() override {
    std::cout<<"exit from TearDown" <<std::endl;
  }

  // A helper function that some test uses.
  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_;
};

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

// Tests the default c'tor.
TEST_F(QueueTestSmpl3, DefaultConstructor) {
  // You can access data in the test fixture here.
  EXPECT_EQ(0u, q0_.Size());
}

// Tests Dequeue().
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;
}

// Tests the Queue::Map() function.
TEST_F(QueueTestSmpl3, Map) {
  MapTester(&q0_);
  MapTester(&q1_);
  MapTester(&q2_);
}
}  // namespace

 

posted @ 2023-04-12 09:11  lypbendlf  阅读(31)  评论(0编辑  收藏  举报