Linux下cppunit的基本使用說明文檔及項目測試簡介

Cppunit使用說明文檔

注:此文檔部分內容來源於cppunit源碼解讀,以及https://www.ibm.com/developerworks/cn/linux/l-cppunit/index.htmlhttp://blog.csdn.net/freefalcon/article/details/753819參照該文檔可以更好的理解cppunit的使用,無恥的加了原創

一、CppUnit核心內容主要包括六個方面:

1.測試對象(Test,TestFixture,…):用於開發測試用例,以及對測試用例進行組織管理。

2.測試結果(TestResult):處理測試用例執行結果。TestResult與下面的TestListener採用的是觀察者模式 (Observer Pattern)。

3.測試結果監聽者(TestListener):TestListener作爲TestResult的觀察者,擔任實際的結果處理角色。

4.結果輸出(Outputter):將結果進行輸出,可以制定不同的輸出格式。

5.對象工廠(TestFactory):用於創建測試對象,對測試用例進行自動化管理。

6.測試執行體(TestRunner):用於運行一個測試。

二、各模塊的主要類繼承結構

這裏寫圖片描述

三、CppUnit的原理

​ 在CppUnit中,一個或一組測試用例的測試對象被稱爲Fixture。Fixture就是被測試的目標,可能是一個對象或者一組相關的對象,甚至一個函數。(在此Fixture爲下述函數中的GetAmount及GetCurrency)

​ 有了被測試的 fixture,就可以對這個fixture 的某個功能、某個可能出錯的流程編寫測試代碼,這樣對某個方面完整的測試被稱爲TestCase(測試用例)。通常寫一個 TestCase 的步驟包括:

(1).對 fixture 進行初始化,及其他初始化操作,比如:生成一組被測試的對象,初始化值;
(2).按照要測試的某個功能或者某個流程對 fixture 進行操作;
(3).驗證結果是否正確;
(4).對fixture 的及其他的資源釋放等清理工作。

​ 對 fixture 的多個測試用例,通常(1)、(4)部分代碼都是相似的,CppUnit 在很多地方引入了 setUp 和 tearDown 虛函數。可以在 setUp 函數裏完成(1)初始化代碼,而在 tearDown 函數中完成(4)代碼。具體測試用例函數中只需要完成(2)(3)部分代碼即可,運行時 CppUnit 會自動爲每個測試用例函數運行 setUp,之後運行 tearDown,這樣測試用例之間就沒有交叉影響。

​ 對 fixture 的所有測試用例可以被封裝在一個 CppUnit::TestFixture 的子類(命名慣例是[ClassName]Test)中。然後定義這個fixture 的 setUp 和 tearDown 函數,爲每個測試用例定義一個測試函數(命名慣例是 testXXX)

​ 要把對 fixture 的一個測試函數轉變成一個測試用例,需要生成一個 CppUnit::TestCaller 對象。而最終運行整個應用程序的測試代碼的時候,可能需要同時運行對一個 fixture 的多個測試函數,甚至多個 fixture 的測試用例。CppUnit 中把這種同時運行的測試案例的集合稱爲 TestSuite。而 TestRunner 則運行測試用例或者 TestSuite,具體管理所有測試用例的生命週期。目前提供了 3 類TestRunner,包括:

CppUnit::TextUi::TestRunner   // 文本方式的TestRunner,下述例子爲文本方式
CppUnit::QtUi::TestRunner    // QT方式的TestRunner
CppUnit::MfcUi::TestRunner    // MFC方式的TestRunner
四、驗證測試結果的方式
// 確信condition爲真
CPPUNIT_ASSERT(condition)       
// 當condition爲假時失敗, 並打印message
CPPUNIT_ASSERT_MESSAGE(message, condition)      
// 當前測試失敗, 並打印message
CPPUNIT_FAIL(message)            
// 確信兩者相等
CPPUNIT_ASSERT_EQUAL(expected, actual)    
// 失敗的同時打印message
CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual)  
// 當expected和actual之間差大於delta時失敗
CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta)  
// 判斷執行表達式expression後是否拋出ExceptionType異常
CPPUNIT_ASSERT_THROW(expression, ExceptionType)
// 執行表達式expression後無異常拋出
CPPUNIT_ASSERT_NO_THROW(expression)
五、測試結果輸出方式

測試結果輸出有三種,鏈接如下
https://www.ibm.com/developerworks/cn/linux/l-cppunit/index.html
此例用的是xml的輸出方式,以xml輸出的核心部分如下:

std::ofstream xmlFileOut("cpptestresults.xml");
CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
xmlOut.write();         //將結果寫入xml
xmlFileOut.close();
六、代碼如下
一、被測代碼

1、Money.h

#ifndef _MONEY_H  
#define _MONEY_H  

#include <iostream>  
#include <string>  
using namespace std;  

class CMoney  
{  
public:  
  CMoney( double amount, string currency )  
    : m_amount( amount )  
    , m_currency( currency )  
  {  
  }  
  ~CMoney(){}  
  double GetAmount() const;  
  string GetCurrency() const;     
private:  
  double m_amount;  
  string m_currency;  
};  

#endif

2、Money.cpp

#include <iostream>  
#include <string>  
#include "Money.h"    
using namespace std;  

double CMoney::GetAmount() const
{  
  return m_amount;  
}  
string CMoney::GetCurrency() const  
{  
  return m_currency;  
}
二、測試代碼

1、Money_Test.h

#ifndef _MONEY_TEST_H  
#define _MONEY_TEST_H  

#include "cppunit/extensions/HelperMacros.h"  
#include "Money.h"  

class CMoneyTest:public CppUnit::TestFixture  
{  
    /*聲明一個TestSuite*/  
    CPPUNIT_TEST_SUITE(CMoneyTest);  

    /*添加測試用例到TestSuite,定義新的測試用例都要在這裏聲明; 
    * 如果此處未聲明某個測試用例,程序編譯和運行都不會報錯 
    * 僅僅是該測試用例不會被執行。 
    */  
    CPPUNIT_TEST(testConstructor);  
    CPPUNIT_TEST(testOptorEqual);  
    CPPUNIT_TEST(testOptorNotEqual);  
    CPPUNIT_TEST(testOptorAdd);  

    /*TestSuite聲明完成*/  
    CPPUNIT_TEST_SUITE_END();  

public:  
    CMoneyTest(){}  
    /*初始化 */  
    void setUp();  
    /*清除動作 */  
    void tearDown();  

    /*test app in Money.cpp*/  
    /*test case */  
    void testConstructor();  
};  
#endif 

2、Money_Test.cpp

#include "Money_Test.h"  
#include "Money.h"  
#include <string>  

using namespace std;  

/* 將該TestSuite註冊到名字爲“alltest”的TestSuite中,如果未定義會自動定義,也可以使用CPPUNIT_TEST_SUITE_REGISTRATION( MathTest );定義到全局未命名的TestSuite中 */  

CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CMoneyTest,"alltest");  

/*初始化動作*/  
void CMoneyTest::setUp()  
{  

}  

/*清除動作*/  
void CMoneyTest::tearDown()  
{  

}  

/*編寫測試用例, 
 * 此處編寫一個用例分別來測試CMoney類的一個成員函數
 * 如果有其他測試用例,繼續添加即可
*/  
/*test app in Money.cpp*/  

/*test constructor*/  
void CMoneyTest::testConstructor()  
{  
    double dNum = 22124.44;  
    string sCurrency = "DD";  
    CMoney MyMoney(dNum, sCurrency);  

    CPPUNIT_ASSERT_EQUAL(dNum, MyMoney.GetAmount());  
    CPPUNIT_ASSERT_EQUAL(sCurrency, MyMoney.GetCurrency());  

}

3、Money_Test_Main.cpp

#include <cppunit/extensions/TestFactoryRegistry.h>  
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/XmlOutputter.h>

int main()  
{  
    CppUnit::TestResult controller;         //測試結果
    CppUnit::TestResultCollector result;    //收集結果
    controller.addListener( &result );      //監聽

    CppUnit::TextUi::TestRunner runner;     //測試文本類型

    /*從註冊的TestSuite獲取特定的TestSuite, 
沒有參數的話則獲取未命名的TestSuite*/  
    CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry("alltest");  

    /*添加這個TestSuite到TestRunner中*/  
    runner.addTest(registry.makeTest());  

    /*運行測試*/  
    runner.run( controller );  

    std::ofstream xmlFileOut("cpptestresults.xml"); //構造輸出文件流
    CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
    xmlOut.write();         //將結果寫入xml
    xmlFileOut.close();

    return 0;
}
七、編譯

1、g++ -lcppunit -ldl -o test Money_main.cpp Money_Test.cpp Money.cpp

2、如果是多文件項目,請編寫makefile(可以根據原來的makefile微調即可,主要調整包含cpp的部分),並添加-lcppunit -ldl

八、其他

什麼叫做樁代碼(測試樁),簡而言之就是代替某些代碼的代碼。
如果測試中小型項目,只需把註冊名字統一,然後不同類可以用不同cpp文件測試
目前暫時想到這麼多,如後續遇到問題再補充,我們只能儘可能的多想到問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章