CppUnit測試架構入門(2)

來源:互聯網
上載者:User
CppUnit測試架構入門(2)

Author: Cpluser
Website:http://www.enjoyimage.com
Email:enjoyimage@163.com
Blog:http://blog.csdn.net/cpluser/

示範代碼下載

三、CppUnit開發環境設定
 
認識了CppUnit的測試環境,想必你已經是在磨拳擦掌,準備在你的開發過程中感受一下測試驅動開發的感覺了。不過,在使用CppUnit前,還需要設定一下你的開發環境。
 
1、CppUnit的lib和dll
CppUnit為我們提供了兩套架構庫,一個為靜態lib,一個為動態dll。
 
cppunit project:靜態lib
cppunit_dll project:動態dll和lib
 
在開發中我們可以根據實際情況作出選擇。進入src檔案夾,開啟CppUnitLibraries.dsw。分別編譯這兩個project,輸出位置均為lib檔案夾。
另外一個需要關注的project是TestRunner,它輸出一個dll,提供了一個基於GUI 方式的測試環境,即前面我們提到的兩種測試環境之一。我們也需要編譯這個project,輸出位置亦為lib檔案夾。
為了方便開發,我們把這些編譯出來的lib和dll(包括Debug版和Release版) copy 到我們自己建立的一個檔案夾中(當然你也可以不這麼做),例如F:/cppunit1.9.0/lib/,同時我們也把CppUnit原始碼中include檔案夾copy到我們自己的include檔案夾下。然後在VC的tools/options/directories/include files和library files中設定include路徑和lib路徑。最後別忘了在你的project中link正確的lib。
 
2、在你的VC project中開啟RTTI開關。
具體位置Project Settings/C++/C++ Language。
 
3、為TestRunner.dll設定環境變數
TestRunner.dll為我們提供了基於GUI的測試環境。為了讓我們的測試程式能正確的調用它,TestRunner.dll必須位於你的測試程式的路徑下。但最簡單的方法是在作業系統的環境變數Path中添TestRunner.dll的路徑,這樣是最省事的。
 
四、你的第一個TDD example
 
一切準備就緒,現在我們可以來看看怎樣添加測試代碼了。前面我們提到過,CppUnit最小的測試單位是TestCase,多個相關TestCase組成一個TestSuite。要添加測試代碼最簡單的方法就是利用CppUnit為我們提供的幾個宏來進行(當然還有其他的手工加入方法,但均是殊途同歸,大家可以查閱CppUnit標頭檔中的示範代碼)。這幾個宏是:
 
CPPUNIT_TEST_SUITE() 開始建立一個TestSuite
CPPUNIT_TEST() 添加TestCase
CPPUNIT_TEST_SUITE_END() 結束建立TestSuite
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION() 添加一個TestSuite到一個指定的TestFactoryRegistry工廠
 
感興趣的朋友可以在HelperMacros.h看看這幾個宏的聲明,本文在此不做詳述。
 
1、一個實現兩個整數相加的類
假定我們要實現一個類,類名暫且取做CPlus,它的功能主要是實現兩個數相加(多簡單的一個類啊,這也要測試嗎?不要緊,我們只是瞭解怎樣加入測試代碼來測試它就行了,所以越簡單越好)。 假定這個類要實現的相加的方法是:
 
int Add(int nNum1, int nNum2);
 
Ok,那我們先來寫測試這個方法的代碼吧。TDD 可是先寫測試代碼,後寫產品代碼(CPlus)的哦!先寫的測試代碼往往是不能運行或編譯的,我們的目標是在寫好測試代碼後寫產品代碼,使之編譯通過,然後再進行重構。這就是Kent Beck說的“red/green/refactor”( 還記得基於GUI的測試環境的狀態條嗎?)。所以,上面的類名和方法應該還只是在你的心裡,還只是你的idea而已。
 
2、在VC中為測試代碼建立一個 Project
通常,測試代碼和被測試對象是處於不同的Project中的。這樣就不會讓你的產品代碼被測試代碼所“汙染 ”。
在本例中,我們將建立一個基於GUI 方式的測試環境。在VC中,我們建立一個基於對話方塊的Project。別忘了link正確的lib,本例中我們使用靜態CppUnit lib。由於我們希望這個Project運行後顯示的是圖2這樣的介面,所以我們需要在App的 Instance()中屏蔽掉原有的對話方塊,代之以CppUnit的GUI。
 
CppUnit::MfcUi::TestRunner runner;   runner.addTest(PlusTest::suite()); //添加測試   runner.run(); //show UI   /*   CCPlusTestDlg dlg;   m_pMainWnd = &dlg;   int nResponse = dlg.DoModal();   if (nResponse == IDOK)   {      // TODO: Place code here to handle when the dialog is      // dismissed with OK   }   else if (nResponse == IDCANCEL)   {      // TODO: Place code here to handle when the dialog is      // dismissed with Cancel    }   */
 
前面我們提到過,TestRunner輸出圖2這樣的對話方塊,這也是前面我們為什麼要為TestRunner.dll的路徑設定環境變數的原因。
注意:PlusTest::suite()返回一個指向CppUnit::Test的指標.這個指標就是整個測試的起點。CppUnit::TestFactoryRegistry::getRegistry()根據TestSuite的名字返回TestFactoryRegistry工廠,然後調用工廠裡的makeTest()對TestSuite進行組裝,這是個遞迴調用,將建立起一個樹狀的測試結構。
 
namespace PlusTest   {       CppUnit::Test* suite()       {           CppUnit::TestFactoryRegistry &registry =            CppUnit::TestFactoryRegistry::getRegistry(plusSuiteName());           return registry.makeTest();        }   }
 
另外別忘加標頭檔:
#include "CPlusTestSuite.h"
#include <cppunit/ui/mfc/TestRunner.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
 
3、在Project中加入一個類,取名CPlusTestCase
CPlusTestCase從CppUnit::TestCase繼承,代碼如下:
 
class CPlusTestCase : public CppUnit::TestCase   {       CPPUNIT_TEST_SUITE(CPlusTestCase);       CPPUNIT_TEST(testAdd);       CPPUNIT_TEST_SUITE_END();     public:       CPlusTestCase();       virtual ~CPlusTestCase();       void testAdd(); //測試方法   };
 
看到這幾個宏了嗎?它們可是在這大顯身手了一把。
 
CPPUNIT_TEST_SUITE(CPlusTestCase);
CPPUNIT_TEST( testAdd );
CPPUNIT_TEST_SUITE_END();
 
通過這幾個宏,我們就把CPlusTestCase和testAdd註冊到了測試清單當中。
另外,我們需要在Cpp檔案中加入另外一個宏:
 
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CPlusTestCase,PlusTest::plusSuiteName() );
 
它將CPlusTestCase這個TestSuite註冊到一個指定的TestFactory工廠中,這個TestSuite用 PlusTest::plusSuiteName()函數返回的名字來標識(前面介紹的suite()函數中就是通過這個名字來擷取這個工廠的)。plusSuiteName()是PlusTest這個namespace下的一個函數,它返回我們為這個TestSuite建立的名字(本例我們取名為“plus”)。其實我們也可以不用這麼做,直接在宏裡寫入“plus“即可。但是這樣可以防止寫入程式碼帶來的麻煩。
 
在測試類別中,我們添加了一個測試方法:
 
void testAdd();
 
它測試的對象是前面提到的CPlus類的方法:
 
int Add(int nNum1, int nNum2);
 
我們來看看它的實現:
 
void CPlusTestCase::testAdd()   {        CPlus plus;        int nResult = plus.Add(10, 20); //執行Add操作         CPPUNIT_ASSERT_EQUAL(30, nResult); //檢查結果是否等於30   }
 
CPPUNIT_ASSERT_EQUAL是一個判斷結果的宏。CppUnit中類似的其它宏請查閱TestAssert.h,本文在此不做詳述 。
另外,我們還可以覆寫基類的 setUp()、tearDown()兩個函數。這兩個函數實際上是一個模板方法,在測試回合之前會調用setUp()以進行一些初始化的工作,測試結束之後又會調用tearDown()來做一些“善後工作” ,比如資源的回收等等。當然,你也可以不覆寫這兩個函數,因為它們在基類裡定義成了空方法,而不是純虛函數。 
 
另外,Cpp中要加入標頭檔:
#include "plusSuite.h"
 
4、根據測試代碼編寫產品代碼
編寫完上面的測試代碼後,進行編譯。編譯肯定通不過,編譯器會告訴我們CPlus類沒有聲明,因為我們還沒有實現CPlus類呢!現在的工作就是馬上實現CPlus類,讓編譯通過。現在你應該嗅到一點“測試驅動“的味道了吧?
 
在VC中建立一個MFC Extension Dll的Project,在這個Project 中加入類CPlus,它的聲明如下:
 
class AFX_EXT_CLASS CPlus   {      public:          CPlus();          virtual ~CPlus();
public: int Add(int nNum1, int nNum2); };

 

 
僅有一個方法,就是我們的測試代碼要測試的那個方法。來看看它的實現:
 
int CPlus::Add(int nNum1, int nNum2)   {        return nNum1+nNum2;   }
 
非常簡單,不是嗎?現在讓前面那個包含測試代碼的Project dependent這個Project,include 相關標頭檔 ,Rebuild All,你會發現編譯已通過。你體會到了測試代碼驅動產品代碼了嗎?當然我們的這個例子還很簡單 ,沒有重構這一步驟。
運行我們的測試程式,你就會看到6的介面:

圖6

單擊”Browse”, 7:

圖7

這下你應該對前面我們說的TestSuite的名字理解更深了吧。plus是一個測試包TestSuite,它的下麵包含一個測試案例,這個測試案例下面又包含一個測試方法。
 
至此,我們對CppUnit測試架構的應用作了一個詳細的介紹,希望能對你在進行TDD過程中有所協助。
 
參考資料:
CppUnit源碼及說明文檔
 
CppUnit測試架構入門(1)
 
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.