// PlusTestCase.h
class CPlusTestCase : public CppUnit::TestCase
{
CPPUNIT_TEST_SUITE(CPlusTestCase);
CPPUNIT_TEST(testAdd);
CPPUNIT_TEST_SUITE_END();
public:
CPlusTestCase ();
virtual ~ CPlusTestCase ();
void testAdd();
static std::string GetSuiteName();
static CppUnit::Test* GetSuite();
};
// PlusTestCase.cpp
CppUnit::Test* CPlusTestCase::GetSuite()
{
CppUnit::TestFactoryRegistry& reg =
CppUnit::TestFactoryRegistry::getRegistry (CPlusTestCase::GetSuiteName());
return reg.makeTest();
}
記住在PlusTestCase.h中包含頭文件:
#include <cppunit/extensions/TestFactoryRegistry.h>
后, 我們?yōu)閱卧獪y試建立一個UI測試界面.
由于我們希望這個Project運行后顯示的是GUI界面,所以我們需要在App的 InitInstance ()中屏蔽掉原有的對話框,代之以CppUnit的GUI。
我們在CUnitTestApp::InitInstance()函數(shù)中,將原先顯示主對話框的代碼以下面的代碼取代:
CppUnit::MfcUi::TestRunner runner;
runner.addTest(CPlusTestCase::GetSuite());//添加測試
runner.run();//show UI
/* CUnitTestDlg 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
}
*/
切記必須先在UnitTest.cpp中包含頭文件:
#include <cppunit/ui/mfc/TestRunner.h>
#include " PlusTestCase.h "
到此為止, 我們已經(jīng)建立好一個簡單的單元測試框架。測試框架雖然寫好了,但是測試代碼仍然為空,產(chǎn)品代碼也還沒有寫。下面我們來寫測試代碼:
如前所述,在測試類中,我們添加了一個測試方法:
void testAdd();
它測試的對象是前面提到的CPlus類的方法:int Add(int nNum1, int nNum2);(產(chǎn)品代碼) 我們來看看testAdd()的實現(xiàn):記得在PlusTestCase.h中包含頭文件
#include <cppunit/TestAssert.h>
// PlusTestCase.cpp
void CPlusTestCase::testAdd()
{
CPlus plus;
int nResult = plus.Add(10, 20); //執(zhí)行Add操作
CPPUNIT_ASSERT_EQUAL(30, nResult); //檢查結果是否等于30
}
CPPUNIT_ASSERT_EQUAL是一個判斷結果的宏。CppUnit中類似的其它宏請查閱TestAssert.h,本文在此不做詳述 。
另外,我們還可以覆寫基類的 setUp()、tearDown()兩個函數(shù)。這兩個函數(shù)實際上是一個模板方法,在測試運行之前會調用setUp()以進行一些初始化的工作,測試結束 之后又會調用tearDown()來做一些“善后工作” ,比如資源的回收等等。當然,你也可以不覆寫這兩個函數(shù),因為它們在基類里定義成了空方法,而不是純虛函數(shù)。
編寫完上面的測試代碼后,進行編譯。編譯肯定通不過,編譯器會告訴我們CPlus類沒有聲明,因為我們還沒有實現(xiàn)CPlus類呢!現(xiàn)在的工作是馬上實現(xiàn)CPlus類,讓編譯通過。現(xiàn)在你應該嗅到一點“測試驅動”(Test Driven Develop)的味道了吧?
在VC中建立一個MFC Extension Dll的Project,在這個Project 中加入類CPlus,它的聲明如下:
// Plus.h
class AFX_EXT_CLASS CPlus
{
public:
CPlus();
virtual ~CPlus();
public:
int Add(int nNum1, int nNum2);
};
Add在Plus.cpp中實現(xiàn)如下
int CPlus::Add(int nNum1, int nNum2)
{
return nNum1 + nNum2;//這里可以寫一些錯誤的語句,用來看看錯誤的結果
}
非常簡單,不是嗎?現(xiàn)在讓前面那個包含測試代碼的Project dependent這個Project,并且include 相關頭文件 ,Rebuild All,你會發(fā)現(xiàn)編譯已通過。你體會到了測試代碼驅動產(chǎn)品代碼了嗎?當然我們的這個例子還很簡單 ,沒有重構這一步驟。
運行我們的測試程序,單擊Browse,你會看到如下圖所示的界面:
選擇CPlusTestCase::testAdd后,單擊Run,你會看到如下圖所示的界面:
這下你應該對前面我們說的TestSuite的名字理解更深了吧。CPlus是一個測試包TestSuite,它的下面包含一個測試用例,這個測試用例下面又包含一個測試方法。
如果我修改CPlus::Add的代碼如下:
int CPlus::Add(int nNum1, int nNum2)
{
// return nNum1 + nNum2;
return 2;
}
重新編譯通過,運行程序會發(fā)現(xiàn):
GUI顯示有一個單元測試不通過,并顯示出錯的地方和原因,這樣很好的控制Bug了。