<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

    如何用googletest寫(xiě)C++單元測(cè)試

     googletest是一個(gè)用來(lái)寫(xiě)C++單元測(cè)試的框架,它是跨平臺(tái)的,可應(yīng)用在windows、linux、Mac等OS平臺(tái)上。下面,我來(lái)說(shuō)明如何使用最新的1.6版本gtest寫(xiě)自己的單元測(cè)試。

      本文包括以下幾部分:1、獲取并編譯googletest(以下簡(jiǎn)稱為gtest);2、如何編寫(xiě)單元測(cè)試用例;3、如何執(zhí)行單元測(cè)試。4、google test內(nèi)部是如何執(zhí)行我們的單元測(cè)試用例的。

      1. 獲取并編譯gtest

      gtest試圖跨平臺(tái),理論上,它就應(yīng)該提供多個(gè)版本的binary包。但事實(shí)上,gtest只提供源碼和相應(yīng)平臺(tái)的編譯方式,這是為什么呢?google的解釋是,我們?cè)诰幾g出gtest時(shí),有些獨(dú)特的工程很可能希望在編譯時(shí)加許多flag,把編譯的過(guò)程下放給用戶,可以讓用戶更靈活的處理。這個(gè)仁者見(jiàn)仁吧,反正也是免費(fèi)的BSD權(quán)限。

      源碼的獲取地址:http://code.google.com/p/googletest/

      svn checkout

      怎么編譯呢?

      先進(jìn)入gtest目錄(解壓gtest.zip包過(guò)程就不說(shuō)了),執(zhí)行以下兩行命令:

    Changes for 1.6.0:

    * New feature: ADD_FAILURE_AT() for reporting a test failure at the
      given source location -- useful for writing testing utilities.
    。。。 。。。
    Bug fixes and implementation clean-ups.
    * Potentially incompatible changes: disables the harmful 'make install'
      command in autotools.

      就是最下面一行,make install禁用了,郁悶了吧?UNIX的習(xí)慣編譯方法:./configure;make;make install失靈了,只能說(shuō)google比較有種,又開(kāi)始挑戰(zhàn)用戶習(xí)慣了。

      那么怎么編譯呢?

      先進(jìn)入gtest目錄(解壓gtest.zip包過(guò)程就不說(shuō)了),執(zhí)行以下兩行命令:

    g++ -I./include -I./ -c ./src/gtest-all.cc
    ar -rv libgtest.a gtest-all.o

      之后,生成了libgtest.a,這個(gè)就是我們要的東東了。以后寫(xiě)自己的單元測(cè)試,就需要libgtest.a和gtest目錄下的include目錄,所以,這1文件1目錄我們需要拷貝到自己的工程中。

      編譯完成后怎么驗(yàn)證是否成功了呢?(相當(dāng)不友好?。?/p>

    cd ${GTEST_DIR}/make
      make

    如果看到:

    Running main() from gtest_main.cc
    [==========] Running 6 tests from 2 test cases.
    [----------] Global test environment set-up.
    [----------] 3 tests from FactorialTest
    [ RUN      ] FactorialTest.Negative
    [       OK ] FactorialTest.Negative (0 ms)
    [ RUN      ] FactorialTest.Zero
    [       OK ] FactorialTest.Zero (0 ms)
    [ RUN      ] FactorialTest.Positive
    [       OK ] FactorialTest.Positive (0 ms)
    [----------] 3 tests from FactorialTest (0 ms total)

    [----------] 3 tests from IsPrimeTest
    [ RUN      ] IsPrimeTest.Negative
    [       OK ] IsPrimeTest.Negative (0 ms)
    [ RUN      ] IsPrimeTest.Trivial
    [       OK ] IsPrimeTest.Trivial (0 ms)
    [ RUN      ] IsPrimeTest.Positive
    [       OK ] IsPrimeTest.Positive (0 ms)
    [----------] 3 tests from IsPrimeTest (0 ms total)

    [----------] Global test environment tear-down
    [==========] 6 tests from 2 test cases ran. (0 ms total)
    [  PASSED  ] 6 tests.

      那么證明編譯成功了。

      2、如何編寫(xiě)單元測(cè)試用例

      以一個(gè)例子來(lái)說(shuō)。我寫(xiě)了一個(gè)開(kāi)地址的哈希表,它有del/get/add三個(gè)主要方法需要測(cè)試。在測(cè)試的時(shí)候,很自然,我只希望構(gòu)造一個(gè)哈希表對(duì)象,對(duì)之做許多種不同組合的操作,以驗(yàn)證三個(gè)方法是否正常。所以,gtest提供的TEST方式我不會(huì)用,因?yàn)槎鄠€(gè)TEST不能共享同一份數(shù)據(jù),而且還有初始化哈希表對(duì)象的過(guò)程呢。所以我用TEST_F方式。TEST_F是一個(gè)宏,TEST_F(classname, casename){}在函數(shù)體內(nèi)去做具體的驗(yàn)證。

      上面是我要執(zhí)行單元測(cè)試的類圖。那么,我需要寫(xiě)一系列單元測(cè)試用例來(lái)測(cè)試這個(gè)類。用gtest,首先要聲明一個(gè)類,繼承自gtest里的Test類:

    代碼很簡(jiǎn)單:

    class CHashTableTest : public ::testing::Test {
    protected:
     CHashTableTest():ht(100){

     }
     virtual void SetUp() {
      key1 = "testkey1";
      key2 = "testkey2";
     }

     // virtual void TearDown() {}
     CHashTable ht;

     string key1;
     string key2;
    };

      然后開(kāi)始寫(xiě)測(cè)試用例,用例里可以直接使用上面類中的成員。

    TEST_F(CHashTableTest, hashfunc)
    {
     CHashElement he;

     ASSERT_NE(\
       ht.getHashKey((char*)key1.c_str(), key1.size(), 0),\
       ht.getHashKey((char*)key2.c_str(), key2.size(), 0));

     ASSERT_NE(\
       ht.getHashKey((char*)key1.c_str(), key1.size(), 0),\
       ht.getHashKey((char*)key1.c_str(), key1.size(), 1));

     ASSERT_EQ(\
       ht.getHashKey((char*)key1.c_str(), key1.size(), 0),\
       ht.getHashKey((char*)key1.c_str(), key1.size(), 0));
    }

      注意,TEST_F宏會(huì)直接生成一個(gè)類,這個(gè)類繼承自上面我們寫(xiě)的CHashTableTest類。

      gtest提供ASSERT_和EXPECT_系列的宏,用于判斷二進(jìn)制、字符串等對(duì)象是否相等、真假等等。這兩種宏的區(qū)別是,ASSERT_失敗了不會(huì)往下執(zhí)行,而EXPECT_會(huì)繼續(xù)。

      3、如何執(zhí)行單元測(cè)試

      首先,我們自己要有一個(gè)main函數(shù),函數(shù)內(nèi)容非常簡(jiǎn)單:

    #include "gtest/gtest.h"

    int main(int argc, char** argv) {
     testing::InitGoogleTest(&argc, argv);

     // Runs all tests using Google Test.
     return RUN_ALL_TESTS();
    }

      InitGoogleTest會(huì)解析參數(shù)。RUN_ALL_TESTS會(huì)把整個(gè)工程里的TEST和TEST_F這些函數(shù)全部作為測(cè)試用例執(zhí)行一遍。

      執(zhí)行時(shí),假設(shè)我們編譯出的可執(zhí)行文件叫unittest,那么直接執(zhí)行./unittest就會(huì)輸出結(jié)果到屏幕,例如:

    [==========] Running 4 tests from 1 test case.
    [----------] Global test environment set-up.
    [----------] 4 tests from CHashTableTest
    [ RUN      ] CHashTableTest.hashfunc
    [       OK ] CHashTableTest.hashfunc (0 ms)
    [ RUN      ] CHashTableTest.addget
    [       OK ] CHashTableTest.addget (0 ms)
    [ RUN      ] CHashTableTest.add2get
    testCHashTable.cpp:79: Failure
    Value of: getHe->m_pNext==NULL
      Actual: true
    Expected: false
    [  FAILED  ] CHashTableTest.add2get (1 ms)
    [ RUN      ] CHashTableTest.delget
    [       OK ] CHashTableTest.delget (0 ms)
    [----------] 4 tests from CHashTableTest (1 ms total)

    [----------] Global test environment tear-down
    [==========] 4 tests from 1 test case ran. (1 ms total)
    [  PASSED  ] 3 tests.
    [  FAILED  ] 1 test, listed below:
    [  FAILED  ] CHashTableTest.add2get

      可以看到,對(duì)于錯(cuò)誤的CASE,會(huì)標(biāo)出所在文件及其行數(shù)。

     如果我們需要輸出到XML文件,則執(zhí)行./unittest --gtest_output=xml,那么會(huì)在當(dāng)前目錄下生成test_detail.xml 文件,內(nèi)容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <testsuites tests="3" failures="0" disabled="0" errors="0" time="0.001" name="AllTests">
      <testsuite name="CHashTableTest" tests="3" failures="0" disabled="0" errors="0" time="0.001">
        <testcase name="hashfunc" status="run" time="0.001" classname="CHashTableTest" />
        <testcase name="addget" status="run" time="0" classname="CHashTableTest" />
        <testcase name="delget" status="run" time="0" classname="CHashTableTest" />
      </testsuite>
    </testsuites>

      如此,一個(gè)簡(jiǎn)單的單元測(cè)試寫(xiě)完。因?yàn)樘?jiǎn)單,所以不需要使用google mock模擬一些依賴。后續(xù)我再寫(xiě)結(jié)合google mock來(lái)寫(xiě)一些復(fù)雜的gtest單元測(cè)試。

      下面來(lái)簡(jiǎn)單說(shuō)下gtest的工作流程。

      4、google test內(nèi)部是如何執(zhí)行我們的單元測(cè)試用例的

      首先從main函數(shù)看起。

      我們的main函數(shù)執(zhí)行了RUN_ALL_TESTS宏,這個(gè)宏干了些什么事呢?

    #define RUN_ALL_TESTS()\
      (::testing::UnitTest::GetInstance()->Run())

    }  // namespace testing

      原來(lái)是調(diào)用了UnitTest靜態(tài)工廠實(shí)例的Run方法!在gtest里,一切測(cè)試用例都是Test類的實(shí)例!所以,Run方法將會(huì)執(zhí)行所有的Test實(shí)例來(lái)運(yùn)行所有的單元測(cè)試,看看類圖:

      為什么說(shuō)一切單元測(cè)試用例都是Test類的實(shí)例呢?

      我們有兩種寫(xiě)測(cè)試用例的方法,一種就是上面我說(shuō)的TEST_F宏,這要求我們要顯示的定義一個(gè)子類繼承自Test類。在TEST_F宏里,會(huì)再次定義一個(gè)新類,繼承自我們上面定義的子類(兩重繼承哈)。

      第二種就是TEST宏,這個(gè)宏里不要求用戶代碼定義類,但在google test里,TEST宏還是定義了一個(gè)子類繼承自Test類。

      所以,UnitTest的Run方法只需要執(zhí)行所有Test實(shí)例即可。

    個(gè)單元測(cè)試用例就是一個(gè)Test類子類的實(shí)例。它同時(shí)與TestResult,TestCase,TestInfo關(guān)聯(lián)起來(lái),用于提供結(jié)果。

      當(dāng)然,還有EventListen類來(lái)監(jiān)控結(jié)果的輸出,控制測(cè)試的進(jìn)度等。

      以上并沒(méi)有深入細(xì)節(jié),只是大致幫助大家理解,我們寫(xiě)的幾個(gè)簡(jiǎn)單的gtest宏,和單元測(cè)試用例,到底是如何被執(zhí)行的。接下來(lái),我會(huì)通過(guò)gmock來(lái)深入的看看google單元測(cè)試的玩法。

    posted on 2013-08-28 10:39 順其自然EVO 閱讀(593) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2013年8月>
    28293031123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 搡女人免费免费视频观看| 亚洲AV无码一区二区三区网址| 成人a毛片视频免费看| 日韩免费观看一级毛片看看| 亚洲日韩一中文字暮| 久久久久久久免费视频| 色噜噜亚洲男人的天堂| 性感美女视频免费网站午夜| 亚洲精品无码专区| 免费在线观看亚洲| xxxxxx日本处大片免费看| 国产精品V亚洲精品V日韩精品| jizz在线免费观看| 亚洲AV午夜福利精品一区二区 | 精品在线免费观看| 亚洲国产精品久久久久网站| 在线人成精品免费视频| 亚洲校园春色另类激情| 国产一区二区三区无码免费| selaoban在线视频免费精品| 亚洲色偷偷偷鲁综合| 老司机69精品成免费视频| 亚洲理论在线观看| 尤物永久免费AV无码网站| 日日狠狠久久偷偷色综合免费| 亚洲中文字幕无码中文字在线| 久操免费在线观看| 亚洲中文字幕久久久一区| 免费女人18毛片a级毛片视频| 国产免费无码一区二区| 亚洲入口无毒网址你懂的| 四虎影库久免费视频| 久久青草免费91线频观看站街| 亚洲熟妇av午夜无码不卡| 亚洲视频在线一区二区| 最近免费中文在线视频| 国产成人亚洲综合在线| 亚洲综合精品香蕉久久网97| 国产成人精品123区免费视频| 18禁超污无遮挡无码免费网站 | 曰批视频免费30分钟成人|