C++單元測試框架gtest使用


  1. 作用

    1. 作為代碼編碼人員,寫完代碼,不僅要保證編譯通過和運行,還要保證邏輯盡量正確。單元測試是對軟件可測試最小單元的檢查和校驗。單元測試與其他測試不同,單元測試可看作是編碼工作的一部分,應該由程序員完成,也就是說,經過了單元測試的代碼才是已完成的代碼,提交產品代碼時也要同時提交測試代碼。測試部門可以作一定程度的審核。(來自百度百科
    2. 其作用可以歸為四種:

      1. 驗證:驗證程序邏輯的正確性,即使后期升級,通過跑單元測試,也可以看到升級后是否會對舊邏輯有影響
      2. 設計:促使程序員寫出可單獨測試的代碼,從而更容易解耦
      3. 文檔:作為程序使用的sample
      4. 回歸:應對程序升級,也可以集成到code review之前的編譯,自動做回歸,典型用法就是在DevOps的編譯打包階段,例如jeckins編譯完成后,自動觸發單元測試。
    3. gtest是google提供的一套針對C++的單元測試框架,本文主要闡述其原理和使用方法。
    4. 與gtest配套的框架叫gmock,用於打樁,后續有空再寫一篇介紹gmock的使用
  2. 原理

    1. gtest主要由一系列的宏和事件實現。
      1. 宏:有TEST和TEST_F宏,TEST宏針對簡單的測試用例,TEST_F宏針對需要做初始化和資源回收的測試用例,有點像類似C++的構造函數和析構函數,兩個宏都是把參數展開后拼成一個類。
      2. 事件:分為三種事件
        1.   
        2.  測試程序:一個進程,全局事件在該層

        3. 測試套件:一系列測試用例的集合,SetUpTestCase事件在該層(注意,網上很多地方大部分寫的是SetUpTestSuite,應該是老版本)

        4. 測試用例:一個測試用例的事件體現在每個用例前后的SetUp和TearDown

        5. 每個事件可用於下級時間的數據共享以及測試前后的數據處理
  3. 使用

    1. 如果時間充足,想整體了解,可以參考wiki
      1. TEST
        TEST(TestSuiteName, TestName) {
          ... statements ...
        }

        會生成TestSuiteName_TestName_,不同的TestSuiteName可以有相同的TestName,需要注意的是所有的名字都不能有下划線

      2. TEST_F
        TEST_F(TestFixtureName, TestName) {
          ... statements ...
        }

        固定的套件名字

      3. TEST_P
        TEST_P(MyTestSuite, DoesSomething) {
          ...
          EXPECT_TRUE(DoSomething(GetParam()));
          ...
        }

        支持傳遞參數

    2. 事件
      1. 全局事件:需要創建一個自己的類,然后繼承testing::Environment類,分別實現成員函數SetUp()和TearDown(),同時在main函數內進行調用,即"testing::AddGlobalTestEnvironment(new MyEnvironment);",通過調用函數我們可以添加多個全局的事件機制。需要注意的是,全局事件在--gtest_repeat參數大於1的情況下(可以通過--help查看其他參數),會執行多次
        1. 代碼:
          #include <iostream>
          
          #include <gtest/gtest.h>
          
          using namespace std;
          
          class MyEnvironment0 : public testing::Environment {
              public:
                  virtual void SetUp() {
                      cout << "Global event0 : start1" << endl;
                  }
          
                  virtual void TearDown() {
                      cout << "Global event0 : end" << endl;
                  }
          };
          
          class MyEnvironment1 : public testing::Environment {
              public:
                  virtual void SetUp() {
                      cout << "Global event1 : start" << endl;
                  }
          
                  virtual void TearDown() {
                      cout << "Global event1 : end" << endl;
                  }
          };
          
          TEST(GlobalTest0, test0) {
              EXPECT_EQ(1, 1);
          };
          
          TEST(GlobalTest0, test1) {
              EXPECT_EQ(1, 1);
          };
          
          TEST(GlobalTest1, test0) {
              EXPECT_EQ(1, 1);
          };
          
          int main(int argc, char *argv[]) {
              testing::AddGlobalTestEnvironment(new MyEnvironment0);
              testing::AddGlobalTestEnvironment(new MyEnvironment1);
          
              testing::InitGoogleTest(&argc, argv);
          
              return RUN_ALL_TESTS();
          }
          View Code

           

      2. 套件事件:繼承testing::Test,實現兩個靜態函數SetUpTestCase()和TearDownTestCase(),測試套件的事件機制不需要像全局事件機制一樣在main注冊,而是需要將我們平時使用的TEST宏改為TEST_F宏
        1.  代碼:
          #include <iostream>
          
          #include <gtest/gtest.h>
          
          using namespace std;
          
          class MyTestSuite0 : public testing::Test
          {
              protected:
                  // 網上大部分寫的是SetUpTestSuite,google后面升級版本了,改成SetUpTestCase
                  // 相關討論:https://stackoverflow.com/questions/54468799/google-test-using-setuptestsuite-doesnt-seem-to-work
                  static void SetUpTestCase()
                  {
                      cout << "TestSuite event0 : start" << endl;
                  }
          
                  static void TearDownTestCase()
                  {
                      cout << "TestSuite event0 : end" << endl;
                  }
          };
          
          class MyTestSuite1 : public testing::Test
          {
              protected:
                  static void SetUpTestCase()
                  {
                      cout << "TestSuite event1 : start" << endl;
                  }
          
                  static void TearDownTestCase()
                  {
                      cout << "TestSuite event1 : end" << endl;
                  }
          };
          
          // 必須用TEST實現,實現上是拼成一個類MyTestSuite0_test0
          TEST_F(MyTestSuite0, test0)
          {
              EXPECT_EQ(1, 1);
          }
          
          TEST_F(MyTestSuite1, test0)
          {
              EXPECT_EQ(1, 1);
          }
          
          TEST_F(MyTestSuite0, test1)
          {
              EXPECT_EQ(1, 1);
          }
          
          TEST_F(MyTestSuite1, test1)
          {
              EXPECT_EQ(1, 1);
          }
          
          //int main(int argc, char *argv[])
          //{
          //    testing::InitGoogleTEST_F(&argc, argv);
          //
          //    return RUN_ALL_TESTS();
          //}
          View Code

           

      3. 用例事件:測試用例的事件機制的創建和測試套件的基本一樣,不同地方在於測試用例實現的兩個函數分別是SetUp()和TearDown(),這兩個函數不是靜態函數了。SetUp()函數是在一個測試用例的開始前執行。TearDown()函數是在一個測試用例的結束后執行。
        1. 代碼:
          #include <iostream>
          
          #include <gtest/gtest.h>
          
          using namespace std;
          
          class MyTestCase0 : public testing::Test
          {
              protected:
                  virtual void SetUp()
                  {
                      cout << "TestCase event0 : start" << endl;
                  }
          
                  virtual void TearDown()
                  {
                      cout << "TestCase event0 : end" << endl;
                  }
          };
          
          class MyTestCase1 : public testing::Test
          {
              protected:
                  virtual void SetUp()
                  {
                      cout << "TestCase event1 : start" << endl;
                  }
                  virtual void TearDown()
                  {
                      cout << "TestCase event1 : end" << endl;
                  }
          };
          
          TEST_F(MyTestCase0, test0)
          {
              EXPECT_EQ(1, 1);
          }
          
          TEST_F(MyTestCase0, test1)
          {
              EXPECT_EQ(1, 1);
          }
          
          TEST_F(MyTestCase1, test0)
          {
              EXPECT_EQ(1, 1);
          }
          
          TEST_F(MyTestCase1, test1)
          {
              EXPECT_EQ(1, 1);
          }
          
          int main(int argc, char *argv[])
          {
              testing::InitGoogleTest(&argc, argv);
          
              return RUN_ALL_TESTS();
          }
          View Code

           

  4. 代碼

    1. 上傳到個人github中:https://github.com/longbozhan/sample/tree/master/gtest
  5. 參考

    1. https://www.shuzhiduo.com/A/n2d9gnDgJD/
    2. https://google.github.io/googletest/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM