一、googletest簡介
本文使用googletest進行單元測試,這里先簡要介紹一下googletest。googletest(簡稱gtest)是一個跨平台的並且開源的(Linux、Mac OS X、Windows、Cygwin、Windows CE and Symbian)C++單元測試框架,由google公司發布。gtest是為在不同平台上為編寫C++測試而生成的。它提供了豐富的斷言、致命和非致命判斷、參數化、“死亡測試”等。
二、相關的准備工作
本文的內容基於win10+vs2015使用googletest框架進行C++單元測試,那么我們要做的第一個工作就是去下載和配置googletest,以便於我們接下來進行使用。
2.1下載源碼
到https://github.com/google/googletest這個地址去下載googletest的源碼為我們下一步進行編譯做准備。
2.2編譯googletest源碼生成我們需要的庫文件
下載完成之后我們得到的是一個zip格式的壓縮文件,我們將其解壓到合適的目錄(以方便自己查找為原則)。這里我們需要注意兩個文件夾,待會需要使用。
使用vs2015打開msvc/2010里面的gtest.sln,會提示升級VC++編譯器和庫,點擊確定即可。
等待升級完成后,打開gtest項目屬性對話框(可以右鍵單擊項目名,打開屬性),配置工程屬性。按圖中兩種方式修改都是可以的(注意和后面測試項目的屬性設置比較)。
Debug、Release兩個模式都要編譯。
在編譯時會出現“無法啟動程序”字樣,這是正常的,因為我們只是生成了相關的庫文件,並不是可執行文件。
編譯后,在msvc/2010/gtest/下有Win32-Debug、Win32-Release兩個文件夾,並且每個文件夾里面有一個gtestd.lib文件,如下圖所示。
至此,准備階段完成。
2.3必要知識學習
斷言:gtest中采用了大量的宏來包裝斷言,這里的斷言不同於C語言當中的斷言(assert)。
按照其使用方法可以分為兩類:
- ASSERT系列(ASSERT_&系列,當檢查點失敗時,退出當前函數,並非推出當前案例);
- EXPECT系列(EXPECT_*系列的斷言,當檢查點失敗時,繼續往下執行)。
按照常用功能可以依次分為12類,平常主要用到的以下這幾類:
- 布爾值比較
- 數值型數據比較
- 字符串比較
- 浮點數比較
- 近似數比較
- 異常檢測
- 自定義格式函數與參數檢查
布爾值比較 |
||
ASSERT_TRUE(condition) |
EXPECT_TRUE(condition) |
condition == true |
ASSERT_FALSE(condition) |
EXPECT_FALSE(condition) |
condition == false |
數值型數據比較 |
||
ASSERT_EQ (expected, actual) |
EXPECT_EQ (expected, actual) |
expected == actual |
ASSERT_NE (val1, val2) |
EXPECT_NE (val1, val2) |
val1 != val2 |
ASSERT_LT (val1, val2) |
EXPECT_LT (val1, val2) |
val1 < val2 |
ASSERT_LE (val1, val2) |
EXPECT_LE (val1, val2) |
val1 <= val2 |
ASSERT_GT (val1, val2) |
EXPECT_GT (val1, val2) |
val1 > val2 |
ASSERT_GE (val1, val2) |
EXPECT_GE (val1, val2) |
val2 >= val2 |
字符串比較 |
||
ASSERT_STREQ (str1, str2) |
EXPECT_STREQ (str1, str2) |
兩個C字符串內容相同(同時支持char *和wchar_t *類型) |
ASSERT_STRNE (str1, str2) |
EXPECT_STRNE (str1, str2) |
兩個C字符串內容不同(同時支持char *和wchar_t *類型) |
ASSERT_STRCASEEQ (str1, str2) |
EXPECT_STRCASEEQ (str1, str2) |
兩個C字符串內容相同,忽略大小寫(只支持char *類型) |
ASSERT_STRCASENE (str1, str2) |
EXPECT_STRCASENE (str1, str2) |
兩個C字符串內容不同,忽略大小寫(只支持char *類型) |
浮點數比較 |
||
ASSERT_FLOAT_EQ (val1, val2) |
EXPECT_FLOAT_EQ (val1, val2) |
the two float values are almost equal |
ASSERT_DOUBLE_EQ (val1, val2) |
EXPECT_DOUBLE_EQ (val1, val2) |
the two double values are almost equal |
近似數比較 |
||
ASSERT_NEAR (val1, val2, abs_error) |
EXPECT_NEAR (val1, val2, abs_error) |
兩個數值val1和val2的絕對值差不超過abs_error |
|
|
|
|
||
異常檢查 |
||
ASSERT_THROW (statement, exception_type) |
EXPECT_THROW (statement, exception_type) |
拋出指定類型異常 |
ASSERT_THROW(statement) |
EXPECT_THROW(statement) |
拋出任意類型異常 |
ASSERT_NO_THROW(statement) |
EXPECT_NO_THROW(statement) |
不拋異常 |
|
||
函數值與參數檢查(目前最多只支持5個參數) |
||
ASSERT_PRED1(pred1, val1) |
EXPECT_PRED1(pred1, val1) |
pred1(val1) returns true |
ASSERT_PRED2(pred2, val1, val2) |
EXPECT_PRED2(pred2, val1, val2) |
pred2(val1, val2) returns true |
|
||
Windows HRESULT |
||
ASSERT_HRESULT_SUCCEEDED(expression) |
EXPECT_HRESULT_SUCCEEDED(expression) |
expression is a success HRESULT |
ASSERT_HRESULT_FAILED(expression) |
EXPECT_HRESULT_FAILED(expression) |
expression is a failure HRESULT |
|
||
自定義格式函數與參數檢查(目前最多支持5個參數) |
||
ASSERT_PRED_FORMAT1(pred1, val1) |
EXPECT_PRED_FORMAT1(pred1, val1) |
pred1(val1) is successful |
ASSERT_PRED_FORMAT1(pred1, val1, val2) |
EXPECT_PRED_FORMAT1(pred1, val1, val2) |
pred2(val1, val2) is successful |
2.4創建測試項目並配置屬性
在vs2015中,創建Win32控制台應用程序MyTest。
打開項目屬性對話框,配置工程屬性。展開“配置屬性 -> C/C++ -> 常規”,在【附加包含目錄】中添加“.\include”(這里省略了include的相關母目錄,在之前有過關於include的說明,如果忘記在哪找,可以在前邊的內容中復習一下);展開“C/C++ -> 代碼生成”,在【運行庫】中修改為多線程調試DLL(/MDd),如下圖所示。
展開“鏈接器 -> 輸入”,在【附加依賴項】添加剛剛生成的lib文件路徑,注意這里是配置Debug,要輸入Win32-Debug里面的gtestd.lib文件路徑(這里需要注意文件名后面有個d)。
以上就是配置Debug的方式,配置Release只需要把前邊相對應的位置改為Release的相關內容即可。
2.5編寫測試代碼
這里測試代碼主要分為3個文件,主文件FirstGtest.cpp,以及Box類的兩個相關文件CBox.h和CBox.cpp
1 // CBox.h 2 #pragma once 3 #include <string.h> 4 5 //Box類的定義 6 class CBox 7 { 8 public: 9 //構造函數 10 CBox(double length_value, double width_value, double height_value); 11 //默認構造函數 12 CBox(); 13 //volume函數用於計算Box的體積 14 double volume(); 15 16 private: 17 //Box的3個特性:長、寬、高 18 double Length_of_box; 19 double Width_of_box; 20 double Height_of_box; 21 };
1 //FirstGtest.cpp 2 #include"stdafx.h" 3 #include"gtest\gtest.h" 4 #include"CBox.h" 5 6 //CBox測試類,繼承Test對Box進行測試使用 7 class CBox_test : public testing::Test 8 { 9 protected: 10 CBox* c; 11 virtual void SetUp() 12 { 13 c = new CBox(2, 3, 4); 14 } 15 16 virtual void TearDown() 17 { 18 delete this->c; 19 } 20 }; 21 22 TEST(CBox, case1) 23 { 24 CBox box1{ 78.0, 24.0, 18.0 }; 25 CBox box2; 26 EXPECT_LT(23.0, box1.volume()); 27 } 28 29 TEST_F(CBox_test, case2) 30 { 31 EXPECT_EQ(4, c->volume()); 32 } 33 34 int main(int argc, char* argv[]) 35 { 36 testing::InitGoogleTest(&argc, argv); 37 return RUN_ALL_TESTS(); 38 }
1 //CBox.cpp 2 #include "stdafx.h" 3 #include<iostream> 4 #include"CBox.h" 5 6 using namespace std; 7 8 //構造函數定義,包含3個參數: 9 CBox::CBox(double length_value, double width_value, double height_value) 10 { 11 cout << "Constructor called." << endl; 12 Length_of_box = length_value; 13 Width_of_box = width_value; 14 Height_of_box = height_value; 15 } 16 17 //默認構造函數 18 CBox::CBox() 19 { 20 cout << "Default constructor is called." << endl; 21 } 22 23 24 // 計算Box體積函數 25 double CBox::volume() 26 { 27 return Length_of_box * Width_of_box * Height_of_box; 28 }
三、遇到的問題及解決辦法
- 在生成兩個gtestd.lib文件時,編譯器報“不是有效的Win32應用程序”,因為之前寫的程序都是生成可執行程序,而沒有做過只生成庫文件的程序,本能地以為程序出錯了,之后經過查閱資料和以及進一步地深入研究,發現這里只是生成了依賴庫文件(我們也只需要這個庫),並沒有生成可執行文件,所以那是正常的。
- 配置googletest依賴庫時,“配置屬性 -> C/C++ -> 代碼生成”中的【運行庫】,前后沒有設置相同的模式,從而導致找不到對應的庫的情況。
- 在配置googletest時,修改“配置屬性 -> 鏈接器 -> 輸入”中的【附加依賴項】時,只填到了我們所生成的庫文件的目錄,但是沒有添加文件名,報找不到*.obj文件的錯誤,只需要把路徑填寫到庫文件就可以解決這個問題。
作者:耑新新,發布於 博客園
轉載請注明出處,歡迎郵件交流:zhuanxinxin@aliyun.com