資料html
偶然發現了google的測試框架gtest,立刻試了下,效果挺不錯,特別是對於寫c++的人來講,方便不少。之前本身寫c++的模塊,一般是寫好了模塊後再另外定義些函數,而後在函數裏面寫測試用例來測試模塊,若是測試點比較多,光是定義測試函數都要花費很多時間。gtest至關於大大節省了這個過程,用起來很是簡單,直接用宏來定義測試用例,而且有不少豐富的宏來輔助測試,例如斷言、預測值、死亡測試等。java
廢話很少說,先上gtest的一些資料:linux
gtest的代碼託管地址:https://github.com/google/googletest,用git clone下來就能夠了。c++
使用gtest構建測試用例指導:https://github.com/google/googletest/tree/master/googletestgit
gtest英文文檔:https://github.com/google/googletest/blob/master/googletest/docs/Documentation.mdgithub
gtest中文博客:玩轉Google開源C++單元測試框架Google Test系列,這系列博客對gtest的具體使用講解的很是詳細。框架
gmock使用文檔:https://github.com/google/googletest/blob/master/googlemock/docs/Documentation.md函數
gmock中文文檔:Google Mock啓蒙篇單元測試
gtest項目中包含了兩個框架,一個gtest測試框架,一個是gmock框架。gtest相似於java裏面的junit,用來作單元測試的;gmock主要是用來mock待測試模塊依賴的一些對象,幫助你在測試中去除沒必要要的依賴,相似與java的jMock和EasyMock。測試
好了,接下來直接上例子吧(注:下面的例子都是在linux下編譯運行的,若是要在Windows上,須要看看gtest的文檔)。
gtest demo
clone下來gtest後,能夠在googletest目錄中找到make目錄:
,make目錄中的Makefile是gtest幫咱們寫好的一個使用gtest測試框架來測試模塊的例子。咱們只須要把這個文件拷貝到寫測試模塊代碼的目錄,再改下面幾個地方就能夠編譯運行測試模塊。
1 GTEST_DIR = .. #設置gtest的項目目錄 2 3 USER_DIR = ../samples #設置測試代碼所在的目錄 4 5 CPPFLAGS += -isystem $(GTEST_DIR)/include #設置預處理器參數 6 7 CXXFLAGS += -g -Wall -Wextra -pthread #設置編譯器參數 8 9 TESTS = sample1_unittest #設置編譯目標 10 11 。。。 12 13 #下面的目標生成規則改爲測試模塊的 14 15 sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS) 16 17 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc 18 19 sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \ 20 21 $(USER_DIR)/sample1.h $(GTEST_HEADERS) 22 23 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc 24 25 sample1_unittest : sample1.o sample1_unittest.o gtest_main.a 26 27 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
上面都是make腳本的語法,不清楚的能夠先Google下。好了,一塊兒準備就緒後,來看看一個簡單的例子。首先,先寫個要測試的函數:
1 bool IsEven(int n) { 2 return (n % 2) == 0; 3 }
這是一個判斷一個數是否爲偶數的函數,是否是很是的簡單~~下面咱們就來編寫一個簡單的測試案例:
1 TEST(IsEvenTest, EqTest) 2 { 3 EXPECT_FALSE(IsEven(1)); 4 EXPECT_TRUE(IsEven(2)); 5 }
上面能夠看到,編寫一個測試案例是多麼的簡單。咱們使用了TEST這個宏,它有兩個參數,這兩個參數的定義是:[TestSuiteName,TestCaseName],個人理解是TestSuiteName是對某個模塊總案例名,TestCaseName是這個案例中某個case的名字。
對檢查點的檢查,咱們上面使用到了EXPECT_FLASE和EXPECT_TRUE這兩個宏,這兩個宏主要分別用來判斷函數返回值是否爲false和true。Google還包裝了一系列EXPECT_* 和ASSERT_*的宏,而EXPECT系列和ASSERT系列的區別是:
1. EXPECT_* 失敗時,案例繼續往下執行。
2. ASSERT_* 失敗時,直接在當前函數中返回,當前函數中ASSERT_*後面的語句將不會執行。
至於其它具體宏的介紹,能夠經過上面給出的連接來查看。
好了,一塊兒都準備好了,運行的結果是全部的測試都經過。
若是咱們把第一個EXPECT_FALSE改成EXPECT_TRUE的結果呢?答案是測試是失敗的,並且會給出具體出錯在文件中的哪一行,以及出錯的緣由。
這是個很簡單的使用gtest的例子,雖然簡單,但基本涵蓋了使用gtest的流程,並且用這些基本的功能就能解決大部分問題了。至於gtes的一些高級功能,須要的時候能夠查上面連接中的文檔。
gmock demo
編譯運行的方式和gtest相似,Makefile文件在googlemock目錄中的make目錄中,按前面相似的修改這個Makefile文件就行。如今要測試的模塊以下:
1 void func(FooInterface *p) 2 { 3 p->DoThis(); 4 }
這個模塊依賴於實現了抽象類FooInterface的對象,FooInterface類定義以下:
1 class FooInterface { 2 public: 3 virtual ~FooInterface() {} 4 virtual void DoThis() = 0; 5 };
如今咱們須要mock這個抽象類,gmock經過下面的宏來實現:
1 class MockFoo : public FooInterface { 2 public: 3 MockFoo() {} 4 MOCK_METHOD0(DoThis, void()); 5 private: 6 GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo); 7 };
MOCK_METHOD*是一個宏,用來mock父類中的虛函數,*表示函數須要接收*個參數。好了,如今有了Mock類,接下來咱們開始寫測試用例:
1 class MockFoo : public FooInterface { 2 public: 3 MockFoo() {} 4 MOCK_METHOD0(DoThis, void()); 5 private: 6 GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo); 7 };
EXPECT_CALL宏表示將會在後面調用foo對象中的DoThis方法,而且調用次數爲1。
一切都準備好了,如今直接make編譯運行就能夠了,運行結果爲:
若是咱們把最後的delete foo去掉會怎麼樣?
結果就是gmock會報錯提示內存泄露了,但須要注意的是若是在函數func裏面裏面發生了內存泄露,gmock是檢查不出來的。
最後若是咱們把Times中預計的DoThis方法運行次數改成2,結果會怎樣?
結果這個case運行會失敗,預計的次數和實際調用次數不符合。
總結
上面兩個demo也只是個簡單的示例,它們僅僅展現了gtest和gmock的基本用法,這也是咱們在實際測試時常常須要用到的東西,至於一些高級的功能,須要時能夠參考官網文檔。