您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 > cppUnit
CppUnit 快速使用指南
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2014/1/14 9:22:54 ] 推薦標(biāo)簽:CppUnit 開(kāi)源項(xiàng)目 開(kāi)源測(cè)試

        CppUnit 是個(gè)基于 LGPL 的開(kāi)源項(xiàng)目,初版本移植自 JUnit,是一個(gè)非常的開(kāi)源測(cè)試框架。CppUnit 和 JUnit 一樣主要思想來(lái)源于極限編程(XProgramming)。主要功能是對(duì)單元測(cè)試進(jìn)行管理,并可進(jìn)行自動(dòng)化測(cè)試。這樣描述可能沒(méi)有讓您體會(huì)到測(cè)試框架的強(qiáng)大威力,那您在開(kāi)發(fā)過(guò)程中遇到下列問(wèn)題嗎?如果答案是肯定的,應(yīng)該學(xué)習(xí)使用這種技術(shù):

    測(cè)試代碼沒(méi)有很好地維護(hù)而廢棄,再次需要測(cè)試時(shí)還需要重寫(xiě);
    投入太多的精力,找 bug,而新的代碼仍然會(huì)出現(xiàn)類似 bug;
    寫(xiě)完代碼,心里沒(méi)底,是否有大量 bug 等待自己;
    新修改的代碼不知道是否影響其他部分代碼;
    由于牽扯太多,導(dǎo)致不敢進(jìn)行修改代碼;
    ...

        這些問(wèn)題下文都會(huì)涉及。這個(gè)功能強(qiáng)大的測(cè)試框架在國(guó)內(nèi)的 C++ 語(yǔ)言開(kāi)發(fā)人員中使用的不是很多。本文介紹這個(gè)框架,希望能夠用少的代價(jià)盡快掌握這種技術(shù)。下面從基本原理,CppUnit 原理,手動(dòng)使用步驟,通常使用步驟,其他實(shí)際問(wèn)題等方面進(jìn)行討論。以下討論基于 CppUnit1.8.0。

1. 基本原理

        對(duì)于上面的問(wèn)題僅僅說(shuō)明 CppUnit 的使用是沒(méi)有效果的,下面先從測(cè)試的目的,測(cè)試原則等方面簡(jiǎn)要說(shuō)明,然后介紹 CppUnit 的具體使用。

        首先要明確我們寫(xiě)測(cè)試代碼的目的,是驗(yàn)證代碼的正確性或者調(diào)試 bug。這樣寫(xiě)測(cè)試代碼時(shí)有了針對(duì)性,對(duì)那些容易出錯(cuò)的,易變的編寫(xiě)測(cè)試代碼;而不用對(duì)每個(gè)細(xì)節(jié),每個(gè)功能編寫(xiě)測(cè)試代碼,當(dāng)然除非有過(guò)量精力或者可靠性要求。

        編碼和測(cè)試的關(guān)系是密不可分的,推薦的開(kāi)發(fā)過(guò)程并不要等編寫(xiě)完所有或者很多的代碼后再進(jìn)行測(cè)試,而是在完成一部分代碼,比如一個(gè)函數(shù),之后立刻編寫(xiě)測(cè)試代碼進(jìn)行驗(yàn)證。然后再寫(xiě)一些代碼,再寫(xiě)測(cè)試。每次測(cè)試對(duì)所有以前的測(cè)試都進(jìn)行一遍。這樣做的優(yōu)點(diǎn)是,寫(xiě)完代碼,也基本測(cè)試完一遍,心里對(duì)代碼有信心。而且在寫(xiě)新代碼時(shí)不斷地測(cè)試?yán)洗a,對(duì)其他部分代碼的影響能夠迅速發(fā)現(xiàn)、定位。不斷編碼測(cè)試的過(guò)程也是對(duì)測(cè)試代碼維護(hù)的過(guò)程,以便測(cè)試代碼一直是有效的。有了各個(gè)部分測(cè)試代碼的保證,有了自動(dòng)測(cè)試的機(jī)制,更改以前的代碼沒(méi)有什么顧慮了。在極限編程(一種軟件開(kāi)發(fā)思想)中,甚至強(qiáng)調(diào)先寫(xiě)測(cè)試代碼,然后編寫(xiě)符合測(cè)試代碼的代碼,進(jìn)而完成整個(gè)軟件。

        根據(jù)上面說(shuō)的目的、思想,下面總結(jié)一下平時(shí)開(kāi)發(fā)過(guò)程中單元測(cè)試的原則:

    先寫(xiě)測(cè)試代碼,然后編寫(xiě)符合測(cè)試的代碼。至少做到完成部分代碼后,完成對(duì)應(yīng)的測(cè)試代碼;
    測(cè)試代碼不需要覆蓋所有的細(xì)節(jié),但應(yīng)該對(duì)所有主要的功能和可能出錯(cuò)的地方有相應(yīng)的測(cè)試用例;
    發(fā)現(xiàn) bug,首先編寫(xiě)對(duì)應(yīng)的測(cè)試用例,然后進(jìn)行調(diào)試;
    不斷總結(jié)出現(xiàn) bug 的原因,對(duì)其他代碼編寫(xiě)相應(yīng)測(cè)試用例;
    每次編寫(xiě)完成代碼,運(yùn)行所有以前的測(cè)試用例,驗(yàn)證對(duì)以前代碼影響,把這種影響盡早消除;
    不斷維護(hù)測(cè)試代碼,保證代碼變動(dòng)后通過(guò)所有測(cè)試;

        有上面的理論做指導(dǎo),測(cè)試行為可以有規(guī)可循。那么 CppUnit 如何實(shí)現(xiàn)這種測(cè)試框架,幫助我們管理測(cè)試代碼,完成自動(dòng)測(cè)試的?下面看看 CppUnit 的原理。

2. CppUnit 的原理

        在 CppUnit 中,一個(gè)或一組測(cè)試用例的測(cè)試對(duì)象被稱為 Fixture(設(shè)施,下文為方便理解盡量使用英文名稱)。Fixture 是被測(cè)試的目標(biāo),可能是一個(gè)對(duì)象或者一組相關(guān)的對(duì)象,甚至一個(gè)函數(shù)。

        有了被測(cè)試的 fixture,可以對(duì)這個(gè) fixture 的某個(gè)功能、某個(gè)可能出錯(cuò)的流程編寫(xiě)測(cè)試代碼,這樣對(duì)某個(gè)方面完整的測(cè)試被稱為T(mén)estCase(測(cè)試用例)。通常寫(xiě)一個(gè) TestCase 的步驟包括:

    對(duì) fixture 進(jìn)行初始化,及其他初始化操作,比如:生成一組被測(cè)試的對(duì)象,初始化值;
    按照要測(cè)試的某個(gè)功能或者某個(gè)流程對(duì) fixture 進(jìn)行操作;
    驗(yàn)證結(jié)果是否正確;
    對(duì) fixture 的及其他的資源釋放等清理工作。

        對(duì) fixture 的多個(gè)測(cè)試用例,通常(1)(4)部分代碼都是相似的,CppUnit 在很多地方引入了 setUp 和 tearDown 虛函數(shù)?梢栽 setUp 函數(shù)里完成(1)初始化代碼,而在 tearDown 函數(shù)中完成(4)代碼。具體測(cè)試用例函數(shù)中只需要完成(2)(3)部分代碼即可,運(yùn)行時(shí) CppUnit 會(huì)自動(dòng)為每個(gè)測(cè)試用例函數(shù)運(yùn)行 setUp,之后運(yùn)行 tearDown,這樣測(cè)試用例之間沒(méi)有交叉影響。

        對(duì) fixture 的所有測(cè)試用例可以被封裝在一個(gè) CppUnit::TestFixture 的子類(命名慣例是[ClassName]Test)中。然后定義這個(gè)fixture 的 setUp 和 tearDown 函數(shù),為每個(gè)測(cè)試用例定義一個(gè)測(cè)試函數(shù)(命名慣例是 testXXX)。下面是個(gè)簡(jiǎn)單的例子:

class MathTest : public CppUnit::TestFixture {
 protected:
   int m_value1, m_value2;
 public:
   MathTest() {}
 // 初始化函數(shù)
   void setUp () {
     m_value1 = 2;
     m_value2 = 3;
   }
   // 測(cè)試加法的測(cè)試函數(shù)
   void testAdd () {
     // 步驟(2),對(duì) fixture 進(jìn)行操作
     int result = m_value1 + m_value2;
      // 步驟(3),驗(yàn)證結(jié)果是否爭(zhēng)取
     CPPUNIT_ASSERT( result == 5 );
   }
   // 沒(méi)有什么清理工作沒(méi)有定義 tearDown.
 }

        在測(cè)試函數(shù)中對(duì)執(zhí)行結(jié)果的驗(yàn)證成功或者失敗直接反應(yīng)這個(gè)測(cè)試用例的成功和失敗。CppUnit 提供了多種驗(yàn)證成功失敗的方式:

CPPUNIT_ASSERT(condition)     // 確信condition為真
 CPPUNIT_ASSERT_MESSAGE(message, condition) // 當(dāng)condition為假時(shí)失敗, 并打印message
 CPPUNIT_FAIL(message)      // 當(dāng)前測(cè)試失敗, 并打印message
 CPPUNIT_ASSERT_EQUAL(expected, actual)  // 確信兩者相等
 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual) // 失敗的同時(shí)打印message
 CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) // 當(dāng)expected和actual之間差大于delta時(shí)失敗

        要把對(duì) fixture 的一個(gè)測(cè)試函數(shù)轉(zhuǎn)變成一個(gè)測(cè)試用例,需要生成一個(gè) CppUnit::TestCaller 對(duì)象。而終運(yùn)行整個(gè)應(yīng)用程序的測(cè)試代碼的時(shí)候,可能需要同時(shí)運(yùn)行對(duì)一個(gè) fixture 的多個(gè)測(cè)試函數(shù),甚至多個(gè) fixture 的測(cè)試用例。CppUnit 中把這種同時(shí)運(yùn)行的測(cè)試案例的集合稱為 TestSuite。而 TestRunner 則運(yùn)行測(cè)試用例或者 TestSuite,具體管理所有測(cè)試用例的生命周期。目前提供了 3 類TestRunner,包括:

CppUnit::TextUi::TestRunner  // 文本方式的TestRunner
 CppUnit::QtUi::TestRunner  // QT方式的TestRunner
 CppUnit::MfcUi::TestRunner  // MFC方式的TestRunner

        下面是個(gè)文本方式 TestRunner 的例子:

CppUnit::TextUi::TestRunner runner;
 CppUnit::TestSuite *suite= new CppUnit::TestSuite();
 
 // 添加一個(gè)測(cè)試用例
 suite->addTest(new CppUnit::TestCaller<MathTest> (
               "testAdd", testAdd));
 
 // 指定運(yùn)行TestSuite
 runner.addTest( suite );
 // 開(kāi)始運(yùn)行, 自動(dòng)顯示測(cè)試進(jìn)度和測(cè)試結(jié)果
 runner.run( "", true );    // Run all tests and wait


        對(duì)測(cè)試結(jié)果的管理、顯示等功能涉及到另一類對(duì)象,主要用于內(nèi)部對(duì)測(cè)試結(jié)果、進(jìn)度的管理,以及進(jìn)度和結(jié)果的顯示。這里不做介紹。

        下面我們整理一下思路,結(jié)合一個(gè)簡(jiǎn)單的例子,把上面說(shuō)的思路串在一起。

上一頁(yè)123下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd