C++程式的單元測試(轉貼)
阿新 • • 發佈:2019-02-10
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 ®istry =
CppUnit::TestFactoryRegistry::getRegistry(plusSuiteName());
return registry.makeTest(); }}
另外別忘加標頭檔案:
#include "CPlusTestSuite.h"
#include
#include
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,你會發現編譯已通過。你體會到了測試程式碼驅動產品程式碼了嗎?當然我們的這個例子還很簡單 ,沒有重構這一步驟。
執行我們的測試程式,你就會看到介面:
單擊”Browse”,
這下你應該對前面我們說的TestSuite的名字理解更深了吧。plus是一個測試包TestSuite,它的下面包含一個測試用例,這個測試用例下面又包含一個測試方法。
至此,我們對CppUnit測試框架的應用作了一個詳細的介紹,希望能對你在進行TDD過程中有所幫助。
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 ®istry =
CppUnit::TestFactoryRegistry::getRegistry(plusSuiteName());
return registry.makeTest(); }}
另外別忘加標頭檔案:
#include "CPlusTestSuite.h"
#include
#include
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,你會發現編譯已通過。你體會到了測試程式碼驅動產品程式碼了嗎?當然我們的這個例子還很簡單 ,沒有重構這一步驟。
執行我們的測試程式,你就會看到介面:
單擊”Browse”,
這下你應該對前面我們說的TestSuite的名字理解更深了吧。plus是一個測試包TestSuite,它的下面包含一個測試用例,這個測試用例下面又包含一個測試方法。
至此,我們對CppUnit測試框架的應用作了一個詳細的介紹,希望能對你在進行TDD過程中有所幫助。