• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            eXile 的專欄

            Google C++ Testing Framework Primer(zt)

            Google C++ Testing Framework Primer



            翻譯:Ray Li (ray.leex@gmail.com)
            修改日期:2008年7月6日
            原文參見(jiàn):http://code.google.com/p/googletest/wiki/GoogleTestPrimer

            譯文地址:http://www.javaeye.com/topic/212024

             

            Introduction:為什么需要Google C++ 測(cè)試框架?

             

            Google C++ 測(cè)試框架幫助你更好地編寫(xiě)C++測(cè)試。

             

            無(wú)論你是在Linux,Windows,還是Mac環(huán)境下工作,只要你編寫(xiě)C++代碼,Google 測(cè)試框架都可以幫上忙。

             

            那么,哪些因素才能構(gòu)成一個(gè)好的測(cè)試?以及,Google C++ 測(cè)試框架怎樣滿足這些因素?我們相信:

            1. 測(cè)試應(yīng)該是獨(dú)立可重復(fù)的。因?yàn)槠渌麥y(cè)試成功或失敗而導(dǎo)致我們要對(duì)自己的測(cè)試進(jìn)行debug是非常痛苦的。Google C++ 測(cè)試框架通過(guò)將每個(gè)測(cè)試在不同的對(duì)象中運(yùn)行,使得測(cè)試分離開(kāi)來(lái)。當(dāng)一個(gè)測(cè)試失敗時(shí),Google C++ 測(cè)試框架允許你獨(dú)立運(yùn)行它以進(jìn)行快速除錯(cuò)。
            2. 測(cè)試應(yīng)該能夠被很好地組織,并反映被測(cè)代碼的結(jié)構(gòu)。Google C++ 測(cè)試框架將測(cè)試組織成測(cè)試案例,案例中的測(cè)試可以共享數(shù)據(jù)和程序分支。這樣一種通用模式能夠很容易辨識(shí),使得我們的測(cè)試容易維護(hù)。當(dāng)開(kāi)發(fā)人員在項(xiàng)目之間轉(zhuǎn)換,開(kāi)始在一個(gè)新的代碼基上開(kāi)始工作時(shí),這種一致性格外有用。
            3. 測(cè)試應(yīng)該是可移植、可重用的。開(kāi)源社區(qū)有很多平臺(tái)獨(dú)立的代碼,它們的測(cè)試也應(yīng)該是平臺(tái)獨(dú)立的。除開(kāi)一些特殊情況,Google C++ 測(cè)試框架運(yùn)行在不同的操作系統(tǒng)上、與不同的編譯器(gcc、icc、MSVC)搭配,Google C++ 測(cè)試框架的測(cè)試很容易與不同的配置一起工作。
            4. 當(dāng)測(cè)試失敗時(shí),應(yīng)該提供盡可能多的、關(guān)于問(wèn)題的信息。Google C++ 測(cè)試框架在第一個(gè)測(cè)試失敗時(shí)不會(huì)停下來(lái)。相反,它只是將當(dāng)前測(cè)試停止,然后繼續(xù)接下來(lái)的測(cè)試。你也可以設(shè)置對(duì)一些非致命的錯(cuò)誤進(jìn)行報(bào)告,并接著進(jìn)行當(dāng)前的測(cè)試。這樣,你就可以在一次“運(yùn)行-編輯-編譯”循環(huán)中檢查到并修復(fù)多個(gè)bug。
            5. 測(cè)試框架應(yīng)該能將測(cè)試編寫(xiě)人員從一些環(huán)境維護(hù)的工作中解放出來(lái),使他們能夠集中精力于測(cè)試的內(nèi)容。Google C++ 測(cè)試框架自動(dòng)記錄下所有定義好的測(cè)試,不需要用戶通過(guò)列舉來(lái)指明哪些測(cè)試需要運(yùn)行。
            6. 測(cè)試應(yīng)該快速。使用Google C++ 測(cè)試框架,你可以重用多個(gè)測(cè)試的共享資源,一次性完成設(shè)置/解除設(shè)置,而不用使一個(gè)測(cè)試去依賴另一測(cè)試。

            因?yàn)?span id="dfxjdlh" class="hilite1">Google C++ 測(cè)試框架基于著名的xUnit架構(gòu),如果你之前使用過(guò)JUnit或PyUnit的話,你將會(huì)感覺(jué)非常熟悉。如果你沒(méi)有接觸過(guò)這些測(cè)試框架,它也只會(huì)占用你大約10分鐘的時(shí)間來(lái)學(xué)習(xí)基本概念和上手。所以,讓我們開(kāi)始吧!

             

            Note:本文偶爾會(huì)用“Google Test”來(lái)代指“Google C++ 測(cè)試框架”。

             

            基本概念

             

            使用Google Test時(shí),你是從編寫(xiě)斷言開(kāi)始的,而斷言是一些檢查條件是否為真的語(yǔ)句。一個(gè)斷言的結(jié)果可能是成功、非致命失敗,或者致命失敗。如果一個(gè)致命失敗出現(xiàn),他會(huì)結(jié)束當(dāng)前的函數(shù);否則,程序繼續(xù)正常運(yùn)行。

             

            測(cè)試使用斷言來(lái)驗(yàn)證被測(cè)代碼的行為。如果一個(gè)測(cè)試崩潰或是出現(xiàn)一個(gè)失敗的斷言,那么,該測(cè)試失敗;否則該測(cè)試成功。

             

            一個(gè)測(cè)試案例(test case)包含了一個(gè)或多個(gè)測(cè)試。你應(yīng)該將自己的測(cè)試分別歸類到測(cè)試案例中,以反映被測(cè)代碼的結(jié)構(gòu)。當(dāng)測(cè)試案例中的多個(gè)測(cè)試需要共享通用對(duì)象和子程序時(shí),你可以把他們放到一個(gè)測(cè)試固件(test fixture)類中。

             

            一個(gè)測(cè)試程序可以包含多個(gè)測(cè)試案例。

             

            從編寫(xiě)單個(gè)的斷言開(kāi)始,到創(chuàng)建測(cè)試和測(cè)試案例,我們將會(huì)介紹怎樣編寫(xiě)一個(gè)測(cè)試程序。

             

            斷言

             

            Google Test中的斷言是一些與函數(shù)調(diào)用相似的宏。要測(cè)試一個(gè)類或函數(shù),我們需要對(duì)其行為做出斷言。當(dāng)一個(gè)斷言失敗時(shí),Google Test會(huì)在屏幕上輸出該代碼所在的源文件及其所在的位置行號(hào),以及錯(cuò)誤信息。也可以在編寫(xiě)斷言時(shí),提供一個(gè)自定義的錯(cuò)誤信息,這個(gè)信息在失敗時(shí)會(huì)被附加在Google Test的錯(cuò)誤信息之后。

             

            斷言常常成對(duì)出現(xiàn),它們都測(cè)試同一個(gè)類或者函數(shù),但對(duì)當(dāng)前功能有著不同的效果。ASSERT_*版本的斷言失敗時(shí)會(huì)產(chǎn)生致命失敗,并結(jié)束當(dāng)前函數(shù)。EXPECT_*版本的斷言產(chǎn)生非致命失敗,而不會(huì)中止當(dāng)前函數(shù)。通常更推薦使用EXPECT_*斷言,因?yàn)樗鼈冞\(yùn)行一個(gè)測(cè)試中可以有不止一個(gè)的錯(cuò)誤被報(bào)告出來(lái)。但如果在編寫(xiě)斷言如果失敗,就沒(méi)有必要繼續(xù)往下執(zhí)行的測(cè)試時(shí),你應(yīng)該使用ASSERT_*斷言。

             

            因?yàn)槭〉腁SSERT_*斷言會(huì)立刻從當(dāng)前的函數(shù)返回,可能會(huì)跳過(guò)其后的一些的清潔代碼,這樣也許會(huì)導(dǎo)致空間泄漏。根據(jù)泄漏本身的特質(zhì),這種情況 也許值得修復(fù),也可能不值得我們關(guān)心——所以,如果你得到斷言錯(cuò)誤的同時(shí),還得到了一個(gè)堆檢查的錯(cuò)誤,記住上面我們所說(shuō)的這一點(diǎn)。

             

            要提供一個(gè)自定義的錯(cuò)誤消息,只需要使用<<操作符,或一個(gè)<<操作符的序列,將其輸入到框架定義的宏中。下面是一個(gè)例子:

             

             
            1. ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";  
            2. for (int i = 0; i < x.size(); ++i) {  
            3.   EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;  
            4. }  
             

            任何能夠被輸出到ostream中的信息都可以被輸出到一個(gè)斷言宏中——特別是C字符串和string對(duì)象。如果一個(gè)寬字符串 (wchar_t*,windows上UNICODE模式TCHAR*或std::wstring)被輸出到一個(gè)斷言中,在打印時(shí)它會(huì)被轉(zhuǎn)換成UTF-8 編碼。

             

            基本斷言

             

            下面這些斷言實(shí)現(xiàn)了基本的true/false條件測(cè)試。

             

            致命斷言 非致命斷言 驗(yàn)證條件
            ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition為真
            ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition 為假

             

            記住,當(dāng)它們失敗時(shí),ASSERT_*產(chǎn)生一個(gè)致命失敗并從當(dāng)前函數(shù)返回,而EXCEPT_*產(chǎn)生一個(gè)非致命失敗,允許函數(shù)繼續(xù)運(yùn)行。在兩種情況下,一個(gè)斷言失敗都意味著它所包含的測(cè)試失敗。

             

            有效平臺(tái):Linux、Windows、Mac。

             

            二進(jìn)制比較

             

            本節(jié)描述了比較兩個(gè)值的一些斷言。

             

            致命斷言 非致命斷言 驗(yàn)證條件
            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); val1 >= val2

             

            在出現(xiàn)失敗事件時(shí),Google Test會(huì)將兩個(gè)值(Val1Val2)都打印出來(lái)。在ASSERT_EQ*和EXCEPT_EQ*斷言(以及我們隨后介紹類似的斷言)中,你應(yīng)該把你希望測(cè)試的表達(dá)式放在actual(實(shí)際值)的位置上,將其期望值放在expected(期望值)的位置上,因?yàn)?span id="x9hbnnb" class="hilite1">Google Test的測(cè)試消息為這種慣例做了一些優(yōu)化。

             

            參數(shù)值必須是可通過(guò)斷言的比較操作符進(jìn)行比較的,否則你會(huì)得到一個(gè)編譯錯(cuò)誤。參數(shù)值還必須支持<<操作符來(lái)將值輸入到ostream中。所有的C++內(nèi)置類型都支持這一點(diǎn)。

             

            這些斷言可以用于用戶自定義的型別,但你必須重載相應(yīng)的比較操作符(如==、<等)。如果定義有相應(yīng)的操作符,推薦使用ASSERT_*()宏,因?yàn)樗鼈儾粌H會(huì)輸出比較的結(jié)果,還會(huì)輸出兩個(gè)比較對(duì)象。

             

            參數(shù)表達(dá)式總是只被解析一次。因此,參數(shù)表達(dá)式有一定的副作用(side effect,這里應(yīng)該是指編譯器不同,操作符解析順序的不確定性)也是可以接受的。但是,同其他普通C/C++函數(shù)一樣,參數(shù)表達(dá)式的解析順序是不確定的(如,一種編譯器可以自由選擇一種順序來(lái)進(jìn)行解析),而你的代碼不應(yīng)該依賴于某種特定的參數(shù)解析順序。

             

            ASSERT_EQ()對(duì)指針進(jìn)行的是指針比較。即,如果被用在兩個(gè)C字符串上,它會(huì)比較它們是否指向同樣的內(nèi)存地址,而不是它們所指向的字符串是否有相同值。所以,如果你想對(duì)兩個(gè)C字符串(例如,const char*)進(jìn)行值比較,請(qǐng)使用ASSERT_STREQ()宏,該宏會(huì)在后面介紹到。特別需要一提的是,要驗(yàn)證一個(gè)C字符串是否為空(NULL),使用ASSERT_STREQ(NULL, c_string)。但是要比較兩個(gè)string對(duì)象時(shí),你應(yīng)該使用ASSERT_EQ。

             

            本節(jié)中介紹的宏都可以處理窄字符串對(duì)象和寬字符串對(duì)象(string和wstring)。

             

            有效平臺(tái):Linux、Windows、Mac。

             

            字符串比較

             

            該組斷言用于比較兩個(gè)C字符串。如果你想要比較兩個(gè)string對(duì)象,相應(yīng)地使用EXPECT_EQ、EXPECT_NE等斷言。

             

            致命斷言 非致命斷言 驗(yàn)證條件
            ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); 兩個(gè)C字符串有相同的內(nèi)容
            ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); 兩個(gè)C字符串有不同的內(nèi)容
            ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); 兩個(gè)C字符串有相同的內(nèi)容,忽略大小寫(xiě)
            ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); 兩個(gè)C字符串有不同的內(nèi)容,忽略大小寫(xiě)

             

            注意斷言名稱中出現(xiàn)的“CASE”意味著大小寫(xiě)被忽略了。

             

            *STREQ*和*STRNE*也接受寬字符串(wchar_t*)。如果兩個(gè)寬字符串比較失敗,它們的值會(huì)做為UTF-8窄字符串被輸出。

             

            一個(gè)NULL空指針和一個(gè)空字符串會(huì)被認(rèn)為是不一樣的。

             

            有效平臺(tái):Linux、Windows、Mac。

             

            參見(jiàn):更多的字符串比較的技巧(如子字符串、前綴和正則表達(dá)式匹配),請(qǐng)參見(jiàn)[Advanced Guide Advanced Google Test Guide]。

             

            簡(jiǎn)單的測(cè)試

             

            要?jiǎng)?chuàng)建一個(gè)測(cè)試:

            1. 使用TEST()宏來(lái)定義和命名一個(gè)測(cè)試函數(shù),它們是一些沒(méi)有返回值的普通C++函數(shù)。
            2. 在這個(gè)函數(shù)中,與你想要包含的其它任何有效C++代碼一起,使用Google Test提供的各種斷言來(lái)進(jìn)行檢查。
            3. 測(cè)試的結(jié)果由其中的斷言決定;如果測(cè)試中的任意斷言失?。o(wú)論是致命還是非致命),或者測(cè)試崩潰,那么整個(gè)測(cè)試就失敗了。否則,測(cè)試通過(guò)。 
            1. TEST(test_case_name, test_name) {  
            2. ... test body ...  
            3. }  
             

            TEST()的參數(shù)是從概括到特殊的。第一個(gè)參數(shù)是測(cè)試案例的名稱,第二個(gè)參數(shù)是測(cè)試案例中的測(cè)試的名稱。記住,一個(gè)測(cè)試案例可以包含任意數(shù)量的獨(dú)立測(cè)試。一個(gè)測(cè)試的全稱包括了包含它的測(cè)試案例名稱,及其獨(dú)立的名稱。不同測(cè)試案例中的獨(dú)立測(cè)試可以有相同的名稱。

             

            舉例來(lái)說(shuō),讓我們看一個(gè)簡(jiǎn)單的整數(shù)函數(shù):

             

            1. int Factorial(int n); // 返回n的階乘  
             

             

            這個(gè)函數(shù)的測(cè)試案例應(yīng)該看起來(lái)像是:

             

            1. // 測(cè)試0的階乘  
            2. TEST(FactorialTest, HandlesZeroInput) {  
            3.   EXPECT_EQ(1, Factorial(0));  
            4. }  
            5. // 測(cè)試正數(shù)的階乘  
            6. TEST(FactorialTest, HandlesPositiveInput) {  
            7.   EXPECT_EQ(1, Factorial(1));  
            8.   EXPECT_EQ(2, Factorial(2));  
            9.   EXPECT_EQ(6, Factorial(3));  
            10.   EXPECT_EQ(40320, Factorial(8));  
            11. }  
             

             

            Google Test根據(jù)測(cè)試案例來(lái)分組收集測(cè)試結(jié)果,因此,邏輯相關(guān)的測(cè)試應(yīng)該在同一測(cè)試案例中;換句話說(shuō),它們的TEST()的第一個(gè)參數(shù)應(yīng)該是一樣的。在上面的例子中,我們有兩個(gè)測(cè)試,HandlesZeroInput和HandlesPostiveInput,它們都屬于同一個(gè)測(cè)試案例FactorialTest

             

            有效平臺(tái):Linux、Windows、Mac。

             

            測(cè)試固件(Test Fixtures,又做測(cè)試夾具、測(cè)試套件):在多個(gè)測(cè)試中使用同樣的數(shù)據(jù)配置

             

            當(dāng)你發(fā)現(xiàn)自己編寫(xiě)了兩個(gè)或多個(gè)測(cè)試來(lái)操作同樣的數(shù)據(jù),你可以采用一個(gè)測(cè)試固件。它讓你可以在多個(gè)不同的測(cè)試中重用同樣的對(duì)象配置。

             

            要?jiǎng)?chuàng)建測(cè)試固件,只需:

            1. 創(chuàng)建一個(gè)類繼承自testing::Test。將其中的成員聲明為protected:或是public:,因?yàn)槲覀兿胍獜淖宇愔写嫒」碳蓡T。
            2. 在該類中聲明你計(jì)劃使用的任何對(duì)象。
            3. 如果需要,編寫(xiě)一個(gè)默認(rèn)構(gòu)造函數(shù)或者SetUp()函數(shù)來(lái)為每個(gè)測(cè)試準(zhǔn)備對(duì)象。常見(jiàn)錯(cuò)誤包括將SetUp()拼寫(xiě)為Setup()(小寫(xiě)了u)——不要讓它發(fā)生在你身上。
            4. 如果需要,編寫(xiě)一個(gè)析構(gòu)函數(shù)或者TearDown()函數(shù)來(lái)釋放你在SetUp()函數(shù)中申請(qǐng)的資源。要知道什么時(shí)候應(yīng)該使用構(gòu)造函數(shù)/析構(gòu)函數(shù),什么時(shí)候又應(yīng)該使用SetUp()/TearDown()函數(shù),閱讀我們的FAQ。
            5. 如果需要,定義你的測(cè)試所需要共享的子程序。

            當(dāng)我們要使用固件時(shí),使用TEST_F()替換掉TEST(),它允許我們存取測(cè)試固件中的對(duì)象和子程序:

             

            1. TEST_F(test_case_name, test_name) {  
            2. ... test body ...  
            3. }  

             

            TEST()一樣,第一個(gè)參數(shù)是測(cè)試案例的名稱,但對(duì)TEST_F()來(lái)說(shuō),這個(gè)名稱必須與測(cè)試固件類的名稱一些。你可能已經(jīng)猜到了:_F正是指固件。

             

            不幸地是,C++宏系統(tǒng)并不允許我們創(chuàng)建一個(gè)單獨(dú)的宏來(lái)處理兩種類型的測(cè)試。使用錯(cuò)誤的宏會(huì)導(dǎo)致編譯期的錯(cuò)誤。

             

            而且,你必須在TEST_F()中使用它之前,定義好這個(gè)測(cè)試固件類。否則,你會(huì)得到編譯器的報(bào)錯(cuò):“virtual outside class declaration”。

            對(duì)于TEST_F()中定義的每個(gè)測(cè)試,Google Test將會(huì):

            1. 在運(yùn)行時(shí)創(chuàng)建一個(gè)全新的測(cè)試固件
            2. 馬上通過(guò)SetUp()初始化它,
            3. 運(yùn)行測(cè)試
            4. 調(diào)用TearDown()來(lái)進(jìn)行清理工作
            5. 刪除測(cè)試固件。注意,同一測(cè)試案例中,不同的測(cè)試擁有不同的測(cè)試固件。Google Test在創(chuàng)建下一個(gè)測(cè)試固件前總是會(huì)對(duì)現(xiàn)有固件進(jìn)行刪除。Google Test不會(huì)對(duì)多個(gè)測(cè)試重用一個(gè)測(cè)試固件。測(cè)試對(duì)測(cè)試固件的改動(dòng)并不會(huì)影響到其他測(cè)試。

            例如,讓我們?yōu)橐粋€(gè)名為Queue的FIFO隊(duì)列類編寫(xiě)測(cè)試,該類的接口如下:

             
            1. template <typename E> // E為元素類型  
            2. class Queue {  
            3. public:  
            4.   Queue();  
            5.   void Enqueue(const E& element);  
            6.   E* Dequeue(); // 返回 NULL 如果隊(duì)列為空.  
            7.   size_t size() const;  
            8.   ...  
            9. };  

             

            首先,定義一個(gè)固件類。習(xí)慣上,你應(yīng)該把它的名字定義為FooTest,這里的Foo是被測(cè)試的類。

             
            1. class QueueTest : public testing::Test {  
            2. protected:  
            3.   virtual void SetUp() {  
            4.     q1_.Enqueue(1);  
            5.     q2_.Enqueue(2);  
            6.     q2_.Enqueue(3);  
            7.   }  
            8.   // virtual void TearDown() {}  
            9.   Queue<int> q0_;  
            10.   Queue<int> q1_;  
            11.   Queue<int> q2_;  
            12. };  
             

            在這個(gè)案例中,我們不需要TearDown(),因?yàn)槊總€(gè)測(cè)試后除了析構(gòu)函數(shù)外不需要進(jìn)行其它的清理工作了。

             

            接下來(lái)我們使用TEST_F()和這個(gè)固件來(lái)編寫(xiě)測(cè)試。

             

            1. TEST_F(QueueTest, IsEmptyInitially) {  
            2.   EXPECT_EQ(0, q0_.size());  
            3. }  
            4. TEST_F(QueueTest, DequeueWorks) {  
            5.   int* n = q0_.Dequeue();  
            6.   EXPECT_EQ(NULL, n);  
            7.   
            8.   n = q1_.Dequeue();  
            9.   ASSERT_TRUE(n != NULL);  
            10.   EXPECT_EQ(1, *n);  
            11.   EXPECT_EQ(0, q1_.size());  
            12.   delete n;  
            13.   
            14.   n = q2_.Dequeue();  
            15.   ASSERT_TRUE(n != NULL);  
            16.   EXPECT_EQ(2, *n);  
            17.   EXPECT_EQ(1, q2_.size());  
            18.   delete n;  
            19. }  
             

            上面這段代碼既使用了ASSERT_*斷言,又使用了EXPECT_*斷言。經(jīng)驗(yàn)上講,如果你想要斷言失敗后,測(cè)試能夠繼續(xù)進(jìn)行以顯示更多的錯(cuò)誤 時(shí),你應(yīng)該使用EXPECT_*斷言;使用ASSERT_*如果該斷言失敗后繼續(xù)往下執(zhí)行毫無(wú)意義。例如,Dequeue測(cè)試中的第二個(gè)斷言是 ASSERT_TURE(n!= NULL),因?yàn)槲覀冸S后會(huì)n指針解引用,如果n指針為空的話,會(huì)導(dǎo)致一個(gè)段錯(cuò)誤。

             

            當(dāng)這些測(cè)試開(kāi)始時(shí),會(huì)發(fā)生如下情況:

            1. Google Test創(chuàng)建一個(gè)QueueTest對(duì)象(我們把它叫做t1)。
            2. t1.SetUp()初始化t1。
            3. 第一個(gè)測(cè)試(IsEmptyInitiallly)在t1上運(yùn)行。
            4. 測(cè)試完成后,t1.TearDown()進(jìn)行一些清理工作。
            5. t1被析構(gòu)。
            6. 以上步驟在另一個(gè)QueueTest對(duì)象上重復(fù)進(jìn)行,這回會(huì)運(yùn)行DequeueWorks測(cè)試。

            有效平臺(tái):Linux、Windows、Mac。

             

            注意:當(dāng)一個(gè)測(cè)試對(duì)象被構(gòu)造時(shí),Google Test會(huì)自動(dòng)地保存所有的Google Test變量標(biāo)識(shí),對(duì)象析構(gòu)后進(jìn)行恢復(fù)。

             

            調(diào)用測(cè)試

             

            TEST()和TEST_F()向Google Test隱式注冊(cè)它們的測(cè)試。因此,與很多其他的C++測(cè)試框架不同,你不需要為了運(yùn)行你定義的測(cè)試而將它們?nèi)吭倭谐鰜?lái)一次。

             

            在定義好測(cè)試后,你可以通過(guò)RUN_ALL_TESTS()來(lái)運(yùn)行它們,如果所有測(cè)試成功,該函數(shù)返回0,否則會(huì)返回1.注意RUN_ALL_TESTS()會(huì)運(yùn)行你鏈接到的所有測(cè)試——它們可以來(lái)自不同的測(cè)試案例,甚至是來(lái)自不同的文件。

             

            當(dāng)被調(diào)用時(shí),RUN_ALL_TESTS()宏會(huì):

            1. 保存所有的Google Test標(biāo)志。
            2. 為一個(gè)側(cè)測(cè)試創(chuàng)建測(cè)試固件對(duì)象。
            3. 調(diào)用SetUp()初始化它。
            4. 在固件對(duì)象上運(yùn)行測(cè)試。
            5. 調(diào)用TearDown()清理固件。
            6. 刪除固件。
            7. 恢復(fù)所有Google Test標(biāo)志的狀態(tài)。
            8. 重復(fù)上訴步驟,直到所有測(cè)試完成。

            此外,如果第二步時(shí),測(cè)試固件的構(gòu)造函數(shù)產(chǎn)生一個(gè)致命錯(cuò)誤,繼續(xù)執(zhí)行3至5部顯然沒(méi)有必要,所以它們會(huì)被跳過(guò)。與之相似,如果第3部產(chǎn)生致命錯(cuò)誤,第4部也會(huì)被跳過(guò)。

             

            重要:你不能忽略掉RUN_ALL_TESTS()的返回值,否則gcc會(huì)報(bào)一個(gè)編譯錯(cuò)誤。這樣設(shè)計(jì)的理由是自動(dòng)化測(cè)試服務(wù)會(huì)根據(jù)測(cè)試退出返回碼來(lái)決定一個(gè)測(cè)試是否通過(guò),而不是根據(jù)其stdout/stderr輸出;因此你的main()函數(shù)必須返回RUN_ALL_TESTS()的值。

             

            而且,你應(yīng)該只調(diào)用RUN_ALL_TESTS()一次。多次調(diào)用該函數(shù)會(huì)與Google Test的一些高階特性(如線程安全死亡測(cè)試thread-safe death tests)沖突,因而是不被支持的。

             

            有效平臺(tái):Linux、Windows、Mac。

             

            編寫(xiě)main()函數(shù)

             

            你可以從下面這個(gè)樣板開(kāi)始:

             

            1. #include "this/package/foo.h"  
            2. #include <gtest/gtest.h>  
            3. namespace {  
            4. // 測(cè)試Foo類的測(cè)試固件  
            5. class FooTest : public testing::Test {  
            6. protected:  
            7.   // You can remove any or all of the following functions if its body  
            8.   // is empty.  
            9.   FooTest() {  
            10.     // You can do set-up work for each test here.  
            11.   }  
            12.   virtual ~FooTest() {  
            13.     // You can do clean-up work that doesn't throw exceptions here.  
            14.   }  
            15.   // If the constructor and destructor are not enough for setting up  
            16.   // and cleaning up each test, you can define the following methods:  
            17.   virtual void SetUp() {  
            18.     // Code here will be called immediately after the constructor (right  
            19.     // before each test).  
            20.   }  
            21.   virtual void TearDown() {  
            22.     // Code here will be called immediately after each test (right  
            23.     // before the destructor).  
            24.   }  
            25.   // Objects declared here can be used by all tests in the test case for Foo.  
            26. };  
            27.   
            28. // Tests that the Foo::Bar() method does Abc.  
            29. TEST_F(FooTest, MethodBarDoesAbc) {  
            30.   const string input_filepath = "this/package/testdata/myinputfile.dat";  
            31.   const string output_filepath = "this/package/testdata/myoutputfile.dat";  
            32.   Foo f;  
            33.   EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));  
            34. }  
            35.   
            36. // Tests that Foo does Xyz.  
            37. TEST_F(FooTest, DoesXyz) {  
            38.   // Exercises the Xyz feature of Foo.  
            39. }  
            40. }  // namespace  
            41.   
            42. int main(int argc, char **argv) {  
            43.   testing::InitGoogleTest(&argc, argv);  
            44.   return RUN_ALL_TESTS();  
            45. }  

             

            testing::InitGoogleTest()函數(shù)負(fù)責(zé)解析命令行傳入的Google Test標(biāo)志,并刪除所有它可以處理的標(biāo)志。這使得用戶可以通過(guò)各種不同的標(biāo)志控制一個(gè)測(cè)試程序的行為。關(guān)于這一點(diǎn)我們會(huì)在GTestAdvanced中講到。你必須在調(diào)用RUN_ALL_TESTS()之前調(diào)用該函數(shù),否則就無(wú)法正確地初始化標(biāo)示。

             

            在Windows上InitGoogleTest()可以支持寬字符串,所以它也可以被用在以UNICODE模式編譯的程序中。

             

            進(jìn)階閱讀

             

            恭喜你!你已經(jīng)學(xué)到了一些Google Test基礎(chǔ)。你可以從編寫(xiě)和運(yùn)行幾個(gè)Google Test測(cè)試開(kāi)始,再閱讀一下GoogleTestSamples,或是繼續(xù)研究GoogleTestAdvancedGuide,其中描述了很多更有用的Google Test特性。

             

            已知局限

             

            Google Test被設(shè)計(jì)為線程安全的。但是,我們還沒(méi)有時(shí)間在各種平臺(tái)上實(shí)現(xiàn)同步原語(yǔ)(synchronization primitives)。因此,目前從兩個(gè)線程同時(shí)使用Google Test斷言是不安全的。由于通常斷言是在主線程中完成的,因此在大多數(shù)測(cè)試中這都不算問(wèn)題。如果你愿意幫忙,你可以試著在gtest-port.h中實(shí)現(xiàn)必要的同步原語(yǔ)。

            posted on 2008-07-21 11:35 eXile 閱讀(1941) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C/C++

            導(dǎo)航

            <2008年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計(jì)

            常用鏈接

            留言簿(18)

            隨筆分類

            隨筆檔案

            服務(wù)器編程

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            热99RE久久精品这里都是精品免费 | 午夜精品久久久久久久久| 99久久精品久久久久久清纯| 久久久久国产日韩精品网站| 久久综合九色综合网站| 久久精品a亚洲国产v高清不卡| 日本免费一区二区久久人人澡| 亚洲国产成人精品女人久久久| 热99RE久久精品这里都是精品免费 | 品成人欧美大片久久国产欧美| 99久久精品免费| 99精品国产综合久久久久五月天| 国产欧美久久一区二区| 欧美国产成人久久精品| 久久精品成人免费网站| 亚洲国产精品综合久久一线| 国产成人综合久久综合| 久久亚洲精品无码aⅴ大香| 老司机国内精品久久久久| 国产香蕉久久精品综合网| 欧美一区二区精品久久| 久久精品国产亚洲AV影院| 韩国三级中文字幕hd久久精品| 日韩乱码人妻无码中文字幕久久| 久久免费99精品国产自在现线 | 天天躁日日躁狠狠久久| 久久久久亚洲精品无码网址| 精品一区二区久久久久久久网站| 思思久久精品在热线热| 久久国产成人午夜AV影院| 久久婷婷国产麻豆91天堂| 久久精品aⅴ无码中文字字幕不卡| 人妻无码久久精品| 精品人妻伦一二三区久久| 久久精品蜜芽亚洲国产AV| 久久精品国产亚洲AV香蕉| 久久强奷乱码老熟女| 亚洲国产成人精品91久久久 | 亚洲欧美日韩精品久久亚洲区 | 久久精品国产亚洲AV高清热| 日韩精品久久久久久久电影蜜臀|