CPPUnit是由JUnit转化而来的C++程序测试框架, xUnit一员. 这一系列用于单元测试, 采用典型的Stub技术. 开源, 并且源代码很精巧, 设计良好, 很容易懂, 且较短.
根据其提供的CppUnit Cookbook, 写了两个小例子, 都是基于文本界面的. CppUnit可以支持MFC和QT图形界面. 我用的是VS2005, cppunit-1.10.2. 我是自己编译的, 编译examples, 可以自动生成库及例子. 之后要配置环境. 下面可能有些代码来自一些文档, 不详细说明了.
先写一个被测试的类Complex, 超简化的复数类, 如下:
Complex.h文件:
//
Complex.h
#pragma
once
class
MathException
...
{ }
;
class
Complex
...
{ private : double real; double imaginary; friend bool operator == ( const Complex & op1, const Complex & op2); friend Complex operator + ( const Complex & op1, const Complex & op2) throw (MathException); friend void operator / ( const Complex & op1, const Complex & op2); public : Complex( double r, double i = 0.0 ) : real(r), imaginary(i) ... {} public : virtual ~ Complex( void ) ... {} }
;
bool
operator
==
(
const
Complex
&
op1,
const
Complex
&
op2); Complex
operator
+
(
const
Complex
&
op1,
const
Complex
&
op2);
void
operator
/
(
const
Complex
&
op1,
const
Complex
&
op2)
throw
(MathException);
Complex.cpp文件:
//
Complex.cpp
#include
"
Complex.h
"
bool
operator
==
(
const
Complex
&
op1,
const
Complex
&
op2)
...
{ return (op1.real == op2.real && op1.imaginary == op2.imaginary); }
Complex
operator
+
(
const
Complex
&
op1,
const
Complex
&
op2)
...
{ return Complex(op1.real + op2.real, op1.imaginary + op2.imaginary); }
void
operator
/
(
const
Complex
&
op1,
const
Complex
&
op2)
throw
(MathException)
...
{ if (op2.real == 0 && op2.imaginary == 0 ) ... { throw MathException(); } }
第一个测试, 没用CppUnit提供的一些帮助宏.
ComplexTest.h:
//
ComplexTest.h
#pragma
once
#include
"
Complex.h
"
#include
<
cppunit
/
testfixture.h
>
#include
<
cppunit
/
TestAssert.h
>
#include
<
cppunit
/
Test.h
>
#include
<
cppunit
/
TestSuite.h
>
#include
<
cppunit
/
TestCaller.h
>
class
ComplexTest :
public
CppUnit::TestFixture
...
{ private : Complex * m_10_1, * m_1_1, * m_11_2, * m_0_0; public : void setUp() ... { m_10_1 = new Complex( 10 , 1 ); m_1_1 = new Complex( 1 , 1 ); m_11_2 = new Complex( 11 , 2 ); m_0_0 = new Complex( 0 , 0 ); } void tearDown() ... { delete m_10_1; delete m_1_1; delete m_11_2; delete m_0_0; } void testEquality() ... { CPPUNIT_ASSERT( * m_10_1 == * m_10_1); CPPUNIT_ASSERT( ! ( * m_10_1 == * m_11_2)); } void testAddition() ... { CPPUNIT_ASSERT( * m_10_1 + * m_1_1 == * m_11_2); } void testDivide() ... { CPPUNIT_ASSERT_THROW( * m_10_1 / * m_0_0, MathException); } static CppUnit::Test * suite() ... { CppUnit::TestSuite * suiteOfTests = new CppUnit::TestSuite( " ComplexrTest " ); suiteOfTests -> addTest( new CppUnit::TestCaller < ComplexTest > ( " testEquality " , & ComplexTest::testEquality)); suiteOfTests -> addTest( new CppUnit::TestCaller < ComplexTest > ( " testAddition " , & ComplexTest::testAddition)); suiteOfTests -> addTest( new CPPUNIT_NS::TestCaller < ComplexTest > ( " testDivide " , & ComplexTest::testDivide)); return suiteOfTests; } }
;
Main函数, MainTest.cpp:
//
MainTest.cpp
#include
"
ComplexTest.h
"
#include
"
Complex.h
"
#include
<
cppunit
/
TestCase.h
>
#include
<
cppunit
/
BriefTestProgressListener.h
>
#include
<
cppunit
/
CompilerOutputter.h
>
#include
<
cppunit
/
extensions
/
TestFactoryRegistry.h
>
#include
<
cppunit
/
TestResult.h
>
#include
<
cppunit
/
TestResultCollector.h
>
#include
<
cppunit
/
TestRunner.h
>
#include
<
cppunit
/
TestCaller.h
>
int
main(
void
)
...
{ // Create the event manager and test controller CPPUNIT_NS::TestResult controller; // Add a listener that colllects test result CPPUNIT_NS::TestResultCollector result; controller.addListener( & result ); // Add a listener that print dots as test run. CPPUNIT_NS::BriefTestProgressListener progress; controller.addListener( & progress ); // Add the suite to the test runner CPPUNIT_NS::TestRunner runner; runner.addTest(ComplexTest::suite()); // runner.addTest(OtheClass::suite()); runner.run( controller ); return 0 ; }
第二个测试, 使用CppUnit提供的一些帮助宏, 并且用了CPPUNIT_NS::TextTestRunner, 支持提供文本界面的支持, 不用自己写像第一个例子一样一堆的代码.
ComplexTest.h:
//
Complex.h
#pragma
once
#include
"
Complex.h
"
#include
<
cppunit
/
testfixture.h
>
#include
<
cppunit
/
TestAssert.h
>
#include
<
cppunit
/
Test.h
>
#include
<
cppunit
/
TestSuite.h
>
#include
<
cppunit
/
TestCaller.h
>
#include
<
cppunit
/
extensions
/
HelperMacros.h
>
class
ComplexTest :
public
CppUnit::TestFixture
...
{ CPPUNIT_TEST_SUITE(ComplexTest); CPPUNIT_TEST_EXCEPTION(testDivide, MathException); CPPUNIT_TEST(testEquality); CPPUNIT_TEST(testAddition); CPPUNIT_TEST_SUITE_END(); private : Complex * m_10_1, * m_1_1, * m_11_2, * m_0_0; public : void setUp() ... { m_10_1 = new Complex( 10 , 1 ); m_1_1 = new Complex( 1 , 1 ); m_11_2 = new Complex( 11 , 2 ); m_0_0 = new Complex( 0 , 0 ); } void tearDown() ... { delete m_10_1; delete m_1_1; delete m_11_2; delete m_0_0; } void testEquality() ... { CPPUNIT_ASSERT( * m_10_1 == * m_10_1); CPPUNIT_ASSERT( ! ( * m_10_1 == * m_11_2)); } void testAddition() ... { CPPUNIT_ASSERT( * m_10_1 + * m_1_1 == * m_11_2); } void testDivide() ... { * m_10_1 / * m_0_0; } }
;
ComplexTest.cpp:
//
ComplexTest.cpp
#include
"
ComplexTest.h
"
#include
<
cppunit
/
extensions
/
HelperMacros.h
>
CPPUNIT_TEST_SUITE_REGISTRATION(ComplexTest);
Main函数, MainTest.cpp:
//
MainTest.cpp
#include
"
ComplexTest.h
"
#include
"
Complex.h
"
#include
<
cppunit
/
ui
/
text
/
TextTestRunner.h
>
#include
<
cppunit
/
extensions
/
TestFactory.h
>
#include
<
cppunit
/
extensions
/
HelperMacros.h
>
int
main(
void
)
...
{ CPPUNIT_NS::TextTestRunner runner; CPPUNIT_NS::TestFactoryRegistry & registry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); bool wasSucessful = runner.run( "" , false ); return wasSucessful; }
实际上这两个例子是一模一样的, 第二个编写程序更方便.
两篇不错的文章:
http://blog.csdn.net/zgump/archive/2003/01/17/10003.aspx
http://blog.csdn.net/fanyamin/archive/2005/11/20/533248.aspx