-
作用
- 作為代碼編碼人員,寫完代碼,不僅要保證編譯通過和運行,還要保證邏輯盡量正確。單元測試是對軟件可測試最小單元的檢查和校驗。單元測試與其他測試不同,單元測試可看作是編碼工作的一部分,應該由程序員完成,也就是說,經過了單元測試的代碼才是已完成的代碼,提交產品代碼時也要同時提交測試代碼。測試部門可以作一定程度的審核。(來自百度百科)
-
其作用可以歸為四種:
- 驗證:驗證程序邏輯的正確性,即使后期升級,通過跑單元測試,也可以看到升級后是否會對舊邏輯有影響
- 設計:促使程序員寫出可單獨測試的代碼,從而更容易解耦
- 文檔:作為程序使用的sample
- 回歸:應對程序升級,也可以集成到code review之前的編譯,自動做回歸,典型用法就是在DevOps的編譯打包階段,例如jeckins編譯完成后,自動觸發單元測試。
- gtest是google提供的一套針對C++的單元測試框架,本文主要闡述其原理和使用方法。
- 與gtest配套的框架叫gmock,用於打樁,后續有空再寫一篇介紹gmock的使用
-
原理
- gtest主要由一系列的宏和事件實現。
- 宏:有TEST和TEST_F宏,TEST宏針對簡單的測試用例,TEST_F宏針對需要做初始化和資源回收的測試用例,有點像類似C++的構造函數和析構函數,兩個宏都是把參數展開后拼成一個類。
- 事件:分為三種事件
-

-
測試程序:一個進程,全局事件在該層
-
測試套件:一系列測試用例的集合,SetUpTestCase事件在該層(注意,網上很多地方大部分寫的是SetUpTestSuite,應該是老版本)
-
測試用例:一個測試用例的事件體現在每個用例前后的SetUp和TearDown
- 每個事件可用於下級時間的數據共享以及測試前后的數據處理
-
- gtest主要由一系列的宏和事件實現。
-
使用
- 如果時間充足,想整體了解,可以參考wiki
- 宏
- TEST
TEST(TestSuiteName, TestName) { ... statements ... }會生成TestSuiteName_TestName_,不同的TestSuiteName可以有相同的TestName,需要注意的是所有的名字都不能有下划線
- TEST_F
TEST_F(TestFixtureName, TestName) { ... statements ... }固定的套件名字
- TEST_P
TEST_P(MyTestSuite, DoesSomething) { ... EXPECT_TRUE(DoSomething(GetParam())); ... }支持傳遞參數
- TEST
- 事件
- 全局事件:需要創建一個自己的類,然后繼承testing::Environment類,分別實現成員函數SetUp()和TearDown(),同時在main函數內進行調用,即"testing::AddGlobalTestEnvironment(new MyEnvironment);",通過調用函數我們可以添加多個全局的事件機制。需要注意的是,全局事件在--gtest_repeat參數大於1的情況下(可以通過--help查看其他參數),會執行多次
- 代碼:
View Code#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(); }
- 代碼:
- 套件事件:繼承testing::Test,實現兩個靜態函數SetUpTestCase()和TearDownTestCase(),測試套件的事件機制不需要像全局事件機制一樣在main注冊,而是需要將我們平時使用的TEST宏改為TEST_F宏
- 代碼:
View Code#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(); //}
- 代碼:
- 用例事件:測試用例的事件機制的創建和測試套件的基本一樣,不同地方在於測試用例實現的兩個函數分別是SetUp()和TearDown(),這兩個函數不是靜態函數了。SetUp()函數是在一個測試用例的開始前執行。TearDown()函數是在一個測試用例的結束后執行。
- 代碼:
View Code#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(); }
- 代碼:
- 全局事件:需要創建一個自己的類,然后繼承testing::Environment類,分別實現成員函數SetUp()和TearDown(),同時在main函數內進行調用,即"testing::AddGlobalTestEnvironment(new MyEnvironment);",通過調用函數我們可以添加多個全局的事件機制。需要注意的是,全局事件在--gtest_repeat參數大於1的情況下(可以通過--help查看其他參數),會執行多次
-
代碼
- 上傳到個人github中:https://github.com/longbozhan/sample/tree/master/gtest
-
參考
- https://www.shuzhiduo.com/A/n2d9gnDgJD/
- https://google.github.io/googletest/
