Linux下Cppunit的簡單運用

工程師WWW發表於2015-08-28

作業系統:

軟體版本:cppunit-1.12.0.tar.gz

程式碼除錯通過

 

一、           CppUnit的原理

先簡單介紹幾個CppUnit的基本術語:

1、Fixture:一個或一組測試用例的測試物件。可以是你要測試的物件或者函式。

2、TestCase:測試用例。是對測試物件的某個功能或流程編寫的測試程式碼。對一個Fixture,可能有多個測試用例。

3、TestSuite:同時執行的測試用例的集合。可以是一個fixture的多個測試函式、也可以是多個fixture的所有測試用例。

使用時,在測試的主檔案中將TestCase註冊到TestSuite中,並執行。

 

二、 下載與安裝

可以在http://sourceforge.net/projects/cppunit/找到最新的原始碼並下載至本地。我下載的版本是cppunit-1.12.0.tar.gz

 

解壓:tar -zxvf cppunit-1.12.0.tar.gz

進入cppunit-1.12.0的目錄

//因為我是非root使用者,沒有對/usr/local/lib/和/usr/include的相應許可權,//所以將安裝的根目錄設定為我的個人目錄

.configure –prefix=/home/me

make

make install    

這樣,庫檔案就複製到/home/me了。

還要將cppunit-1.12.0中的標頭檔案include複製到/home/me中。

 

三、利用cppunit建立測試的一般框架

通常將測試程式碼和被測的程式碼放在不同的工程裡面,以免對我們要測試的程式碼造成汙染,這也是運用cppunit的優點之一吧。

這樣我們便有兩個工程:

其一、待測工程:~/money

有兩個檔案:

Money.h

 Money.cpp

[c-sharp] view plaincopy
  1. /********************************************** 
  2. Money.h 
  3.  
  4.  
  5. ***********************************************/  
  6. #ifndef _MONEY_H  
  7. #define _MONEY_H  
  8.  
  9. #include <iostream>  
  10. #include <string>  
  11. using namespace std;  
  12.   
  13. class CMoney  
  14. {  
  15. public:  
  16.   CMoney( double amount, string currency )  
  17.     : m_amount( amount )  
  18.     , m_currency( currency )  
  19.   {  
  20.   }  
  21.   
  22.   ~CMoney(){}  
  23.   
  24.   double GetAmount() const;  
  25.   
  26.   string GetCurrency() const;  
  27.   
  28.   bool operator ==( const CMoney &other ) const;  
  29.   
  30.   bool operator !=( const CMoney &other ) const;  
  31.   
  32.   CMoney &operator +=( const CMoney &other );  
  33.   
  34. private:  
  35.   double m_amount;  
  36.   string m_currency;  
  37. };  
  38.  
  39. #endif  

[c-sharp] view plaincopy
  1. /********************************************* 
  2. Money.cpp 
  3.  
  4. ***********************************************/  
  5. #include <iostream>  
  6. #include <string>  
  7. #include "Money.h"  
  8.   
  9. using namespace std;  
  10.   
  11. double CMoney::GetAmount() const  
  12. {  
  13.   return m_amount;  
  14. }  
  15.   
  16. string CMoney::GetCurrency() const  
  17. {  
  18.   return m_currency;  
  19. }  
  20.   
  21. bool CMoney::operator ==( const CMoney &other ) const  
  22. {  
  23.   return ((m_amount == other.m_amount) &&  
  24.          (m_currency == other.m_currency));  
  25. }  
  26.   
  27. bool CMoney::operator !=( const CMoney &other ) const  
  28. {  
  29.   return !(*this == other);  
  30. }  
  31.   
  32. CMoney &CMoney::operator +=( const CMoney &other )  
  33. {  
  34.   if ( m_currency != other.m_currency )  
  35.       cout <<  "Incompatible moneys" << endl;  
  36.   
  37.   m_amount += other.m_amount;  
  38.   return *this;  
  39. }  

測試工程:~/MoneyTest

該工程下有三個檔案:

Money_Test.h

Money_Test.cpp

Money_Test_Main.cpp

這三個檔案的作用分別是:

Money_Test.h:宣告一個TestSuite,並將你所需要的測試用例都在此處進行宣告

Mone_Test.cpp:編寫測試用例

Money_Test_Main.cpp:執行測試。該檔案與具體的測試用例無關。

[c-sharp] view plaincopy
  1. /******************************************* 
  2. Money_Test.h 
  3. 2010.5.28 
  4.  
  5. ********************************************/  
  6. #ifndef _MONEY_TEST_H  
  7. #define _MONEY_TEST_H  
  8.  
  9. #include "cppunit/extensions/HelperMacros.h"  
  10. #include "Money.h"  
  11.   
  12. class CMoneyTest:public CppUnit::TestFixture  
  13. {  
  14.     /*宣告一個TestSuite*/  
  15.     CPPUNIT_TEST_SUITE(CMoneyTest);  
  16.   
  17.     /*新增測試用例到TestSuite,定義新的測試用例都要在這裡宣告; 
  18.       如果此處未宣告某個測試用例,程式編譯和執行都不會報錯 
  19.       僅僅是該測試用例不會被執行。 
  20.      */  
  21.     CPPUNIT_TEST(testConstructor);  
  22.     CPPUNIT_TEST(testOptorEqual);  
  23.     CPPUNIT_TEST(testOptorNotEqual);  
  24.     CPPUNIT_TEST(testOptorAdd);  
  25.   
  26.     /*TestSuite宣告完成*/  
  27.     CPPUNIT_TEST_SUITE_END();  
  28.   
  29. public:  
  30.     CMoneyTest(){}  
  31.     /*初始化 */  
  32.     void setUp();  
  33.     /*清除動作 */  
  34.     void tearDown();  
  35.   
  36.     /*test app in Money.cpp*/  
  37.     /*test case */  
  38.     void testConstructor();  
  39.     void testOptorEqual();  
  40.     void testOptorNotEqual();  
  41.     void testOptorAdd();  
  42. };  
  43. #endif 

 

[c-sharp] view plaincopy
  1. /************************************ 
  2. Money_Test.cpp 
  3. 5.28 
  4.  
  5. ****************************************/  
  6. #include "Money_Test.h"  
  7. #include "Money.h"  
  8. #include <string>  
  9.   
  10. using namespace std;  
  11.   
  12. /* 將該TestSuite註冊到名字為“alltest”的TestSuite中,如果未定義會自動定義,也可以使用CPPUNIT_TEST_SUITE_REGISTRATION( MathTest );定義到全域性未命名的TestSuite中 */  
  13.   
  14. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CMoneyTest,"alltest");  
  15.   
  16. /*初始化動作*/  
  17. void CMoneyTest::setUp()  
  18. {  
  19.   
  20. }  
  21.   
  22. /*清除動作*/  
  23. void CMoneyTest::tearDown()  
  24. {  
  25.   
  26. }  
  27.   
  28. /*編寫測試用例, 
  29. 此處編寫四個用例分別來測試CMoney類的四個成員函式*/  
  30. /*test app in Money.cpp*/  
  31.   
  32. /*test constructor*/  
  33. void CMoneyTest::testConstructor()  
  34. {  
  35.     double dNum = 22124.44;  
  36.     string sCurrency = "DD";  
  37.     CMoney MyMoney(dNum, sCurrency);  
  38.   
  39.     CPPUNIT_ASSERT_EQUAL(dNum, MyMoney.GetAmount());  
  40.     CPPUNIT_ASSERT_EQUAL(sCurrency, MyMoney.GetCurrency());  
  41.   
  42. }  
  43.   
  44.   
  45. /*test operator ==()*/  
  46. void CMoneyTest::testOptorEqual()  
  47. {  
  48.     // Set up  
  49.     const CMoney money123FF( 123, "FF" );  
  50.     const CMoney money123USD( 123, "USD" );  
  51.     const CMoney money12FF( 12, "FF" );  
  52.     const CMoney money12USD( 12, "USD" );  
  53.   
  54.     // Process & Check  
  55.     CPPUNIT_ASSERT(money123FF == money123FF);    // ==  
  56.     CPPUNIT_ASSERT(!(money12FF == money123FF));     // != amount  
  57.     CPPUNIT_ASSERT(!(money123USD == money123FF));   // != currency  
  58.     CPPUNIT_ASSERT(!(money12USD == money123FF));     
  59. // != currency and != amount  
  60.   
  61. }  
  62.   
  63. /*test operator!=()*/  
  64. void CMoneyTest::testOptorNotEqual()  
  65. {  
  66.     // Set up  
  67.     const CMoney money123FF( 123, "FF" );  
  68.     const CMoney money123USD( 123, "USD" );  
  69.     const CMoney money12FF( 12, "FF" );  
  70.     const CMoney money12USD( 12, "USD" );  
  71.   
  72.     // Process & Check  
  73.     CPPUNIT_ASSERT(!(money123FF != money123FF));    // ==  
  74.     CPPUNIT_ASSERT(money12FF != money123FF);     // != amount  
  75.     CPPUNIT_ASSERT(money123USD != money123FF);   // != currency  
  76.     CPPUNIT_ASSERT(money12USD != money123FF);      
  77. // != currency and != amount  
  78.   
  79. }  
  80.   
  81. /*test operator+=()*/  
  82. void CMoneyTest::testOptorAdd()  
  83. {  
  84.   // Set up  
  85.   const CMoney money12FF( 12, "FF" );  
  86.   const CMoney expectedMoney( 135, "FF" );  
  87.   
  88.   // Process  
  89.   CMoney money( 123, "FF" );  
  90.   money += money12FF;  
  91.   
  92.   // Check  
  93.   CPPUNIT_ASSERT( expectedMoney ==  money );           // add works  
  94. }  
[c-sharp] view plaincopy
  1. /**************************************************** 
  2. Money_Test_Main.cpp 
  3. 2010.5.28 
  4.  
  5. ********************************************************/  
  6. #include <cppunit/extensions/TestFactoryRegistry.h>  
  7. #include <cppunit/ui/text/TestRunner.h>  
  8.   
  9. int main()  
  10. {  
  11.     CppUnit::TextUi::TestRunner runner;  
  12.   
  13.     /*從註冊的TestSuite獲取特定的TestSuite, 
  14. 沒有引數的話則獲取未命名的TestSuite*/  
  15.     CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry("alltest");  
  16.   
  17.     /*新增這個TestSuite到TestRunner中*/  
  18.     runner.addTest(registry.makeTest());  
  19.   
  20.     /*執行測試*/  
  21.     runner.run();  
  22. }  

CppUnit 提供的驗證成功失敗的方式有:

       CPPUNIT_ASSERT(condition)                              // 確信condition為真

       CPPUNIT_ASSERT_MESSAGE(message, condition)   // 當condition為假時失敗, 並列印message

       CPPUNIT_FAIL(message)                                    // 當前測試失敗, 並列印message

       CPPUNIT_ASSERT_EQUAL(expected, actual)            // 確信兩者相等

       CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual)      // 失敗的同時列印message

       CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta)      // 當expected和actual之間差大於delta時失敗

 

關於CPPUNIT_ASSERT_EQUAL還有一點要說明,該巨集對於expected和actual是有要求的,也就是所謂的Requirement:

  • 具有相同的型別(比如都是std::string)
  • 可以使用<<序列化到std::strstream(assertion_traits<T>::toString中指明)
  • 能用==作比較(assertion_traits<T>::equal中指明)

不過,後兩條可以通過為assertion_traits定製特化版本去除掉。

四、編譯與除錯

編譯、連結動態庫:

g++ -o test Money_Test.cpp Money_Test_Main.cpp ~/money/Money.cpp -I ~/money -I ~/cppunit/include -lcppunit -ldl -L ~/cppunit/lib

執行前要將共享庫的目錄放到LD_LIBRARY_PATH中。

export LD_LIBRARY_PATH=~/cppunit/lib:$LD_LIBRARY_PATH

執行:

       ./test

測試結果:

OK (4 tests)

說明所寫的4個測試用例均成功。

 

 

參考資料

Tx7do@上海半丁 Linux下的CppUnit 的HelloWorld手記

李群:便利的開發工具 CppUnit 快速使用指南

http://www.ibm.com/developerworks/cn/linux/l-cppunit/index.html

CppUnit使用指南

相關文章