// 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>
后, 我们为单元测试建立一个UI测试界面.
由于我们希望这个Project运行后显示的是GUI界面,所以我们需要在App的 InitInstance ()中屏蔽掉原有的对话框,代之以CppUnit的GUI。
我们在CUnitTestApp::InitInstance()函数中,将原先显示主对话框的代码以下面的代码取代:
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 "
到此为止, 我们已经建立好一个简单的单元测试框架。测试框架虽然写好了,但是测试代码仍然为空,产品代码也还没有写。下面我们来写测试代码:
如前所述,在测试类中,我们添加了一个测试方法:
void testAdd();
它测试的对象是前面提到的CPlus类的方法:int Add(int nNum1, int nNum2);(产品代码) 我们来看看testAdd()的实现:记得在PlusTestCase.h中包含头文件
#include <cppunit/TestAssert.h>
// PlusTestCase.cpp
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()来做一些“善后工作” ,比如资源的回收等等。当然,你也可以不覆写这两个函数,因为它们在基类里定义成了空方法,而不是纯虚函数。
编写完上面的测试代码后,进行编译。编译肯定通不过,编译器会告诉我们CPlus类没有声明,因为我们还没有实现CPlus类呢!现在的工作是马上实现CPlus类,让编译通过。现在你应该嗅到一点“测试驱动”(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中实现如下
int CPlus::Add(int nNum1, int nNum2)
{
return nNum1 + nNum2;//这里可以写一些错误的语句,用来看看错误的结果
}
非常简单,不是吗?现在让前面那个包含测试代码的Project dependent这个Project,并且include 相关头文件 ,Rebuild All,你会发现编译已通过。你体会到了测试代码驱动产品代码了吗?当然我们的这个例子还很简单 ,没有重构这一步骤。
运行我们的测试程序,单击Browse,你会看到如下图所示的界面:
选择CPlusTestCase::testAdd后,单击Run,你会看到如下图所示的界面:
这下你应该对前面我们说的TestSuite的名字理解更深了吧。CPlus是一个测试包TestSuite,它的下面包含一个测试用例,这个测试用例下面又包含一个测试方法。
如果我修改CPlus::Add的代码如下:
int CPlus::Add(int nNum1, int nNum2)
{
// return nNum1 + nNum2;
return 2;
}
重新编译通过,运行程序会发现:
GUI显示有一个单元测试不通过,并显示出错的地方和原因,这样很好的控制Bug了。