524 lines
15 KiB
Plaintext
524 lines
15 KiB
Plaintext
/*! \page cppunit_cookbook CppUnit Cookbook
|
|
Here is a short cookbook to help you get started.
|
|
|
|
|
|
\section simple_test_case Simple Test Case
|
|
You want to know whether your code is working.
|
|
|
|
How do you do it?
|
|
|
|
There are many ways. Stepping through a debugger or
|
|
littering your code with stream output calls are two of
|
|
the simpler ways, but they both have drawbacks.
|
|
Stepping through your code is a good idea, but it
|
|
is not automatic. You have to do it every time you
|
|
make changes. Streaming out text is also fine,
|
|
but it makes code ugly and it generates far more
|
|
information than you need most of the time.
|
|
|
|
Tests in %CppUnit can be run automatically.
|
|
They are easy to set up and once you have
|
|
written them, they are always there to help
|
|
you keep confidence in the quality of your code.
|
|
|
|
To make a simple test, here is what you do:
|
|
|
|
Subclass the \link CppUnit::TestCase TestCase \endlink class.
|
|
Override the method \link CppUnit::TestCase::runTest() runTest()\endlink.
|
|
When you want to check a value, call
|
|
\link CPPUNIT_ASSERT() CPPUNIT_ASSERT(bool) \endlink
|
|
and pass in an expression that is true if the
|
|
test succeeds.
|
|
|
|
For example, to test the equality comparison
|
|
for a Complex number class, write:
|
|
|
|
\code
|
|
class ComplexNumberTest : public CppUnit::TestCase {
|
|
public:
|
|
ComplexNumberTest( std::string name ) : CppUnit::TestCase( name ) {}
|
|
|
|
void runTest() {
|
|
CPPUNIT_ASSERT( Complex (10, 1) == Complex (10, 1) );
|
|
CPPUNIT_ASSERT( !(Complex (1, 1) == Complex (2, 2)) );
|
|
}
|
|
};
|
|
\endcode
|
|
|
|
That was a very simple test. Ordinarily,
|
|
you'll have many little test cases that you'll
|
|
want to run on the same set of objects. To do
|
|
this, use a fixture.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\section fixture Fixture
|
|
A fixture is a known set of objects that
|
|
serves as a base for a set of test cases.
|
|
Fixtures come in very handy when you are
|
|
testing as you develop.
|
|
|
|
Let's try out this style of development and
|
|
learn about fixtures along the away. Suppose
|
|
that we are really developing a complex
|
|
number class. Let's start by defining a
|
|
empty class named Complex.
|
|
|
|
\code
|
|
class Complex {};
|
|
\endcode
|
|
|
|
Now create an instance of ComplexNumberTest
|
|
above, compile the code and see what happens.
|
|
The first thing we notice is a few compiler
|
|
errors. The test uses <tt>operator ==</tt>, but it is
|
|
not defined. Let's fix that.
|
|
|
|
\code
|
|
bool operator==( const Complex &a, const Complex &b)
|
|
{
|
|
return true;
|
|
}
|
|
\endcode
|
|
|
|
Now compile the test, and run it. This time it
|
|
compiles but the test fails.
|
|
We need a bit more to get an <tt>operator ==</tt>working
|
|
correctly, so we revisit the code.
|
|
|
|
\code
|
|
class Complex {
|
|
friend bool operator ==(const Complex& a, const Complex& b);
|
|
double real, imaginary;
|
|
public:
|
|
Complex( double r, double i = 0 )
|
|
: real(r)
|
|
, imaginary(i)
|
|
{
|
|
}
|
|
};
|
|
|
|
bool operator ==( const Complex &a, const Complex &b )
|
|
{
|
|
return a.real == b.real && a.imaginary == b.imaginary;
|
|
}
|
|
\endcode
|
|
|
|
If we compile now and run our test it will pass.
|
|
|
|
Now we are ready to add new operations and
|
|
new tests. At this point a fixture would be
|
|
handy. We would probably be better off when
|
|
doing our tests if we decided to instantiate
|
|
three or four complex numbers and reuse them
|
|
across our tests.
|
|
|
|
Here is how we do it:
|
|
- Add member variables for each part of the
|
|
\link CppUnit::TestFixture fixture \endlink
|
|
- Override \link CppUnit::TestFixture::setUp() setUp() \endlink
|
|
to initialize the variables
|
|
- Override \link CppUnit::TestFixture::tearDown() tearDown() \endlink
|
|
to release any permanent resources you allocated in
|
|
\link CppUnit::TestFixture::setUp() setUp() \endlink
|
|
|
|
\code
|
|
class ComplexNumberTest : public CppUnit::TestFixture {
|
|
private:
|
|
Complex *m_10_1, *m_1_1, *m_11_2;
|
|
public:
|
|
void setUp()
|
|
{
|
|
m_10_1 = new Complex( 10, 1 );
|
|
m_1_1 = new Complex( 1, 1 );
|
|
m_11_2 = new Complex( 11, 2 );
|
|
}
|
|
|
|
void tearDown()
|
|
{
|
|
delete m_10_1;
|
|
delete m_1_1;
|
|
delete m_11_2;
|
|
}
|
|
};
|
|
\endcode
|
|
|
|
Once we have this fixture, we can add the complex
|
|
addition test case and any others that we need
|
|
over the course of our development.
|
|
|
|
|
|
|
|
\section test_case Test Case
|
|
|
|
How do you write and invoke individual tests using a fixture?
|
|
|
|
There are two steps to this process:
|
|
- Write the test case as a method in the fixture class
|
|
- Create a TestCaller which runs that particular method
|
|
|
|
Here is our test case class with a few extra case methods:
|
|
|
|
\code
|
|
class ComplexNumberTest : public CppUnit::TestFixture {
|
|
private:
|
|
Complex *m_10_1, *m_1_1, *m_11_2;
|
|
public:
|
|
void setUp()
|
|
{
|
|
m_10_1 = new Complex( 10, 1 );
|
|
m_1_1 = new Complex( 1, 1 );
|
|
m_11_2 = new Complex( 11, 2 );
|
|
}
|
|
|
|
void tearDown()
|
|
{
|
|
delete m_10_1;
|
|
delete m_1_1;
|
|
delete m_11_2;
|
|
}
|
|
|
|
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 );
|
|
}
|
|
};
|
|
\endcode
|
|
|
|
One may create and run instances for each test case like this:
|
|
|
|
\code
|
|
CppUnit::TestCaller<ComplexNumberTest> test( "testEquality",
|
|
&ComplexNumberTest::testEquality );
|
|
CppUnit::TestResult result;
|
|
test.run( &result );
|
|
\endcode
|
|
|
|
The second argument to the test caller constructor is the address of
|
|
a method on ComplexNumberTest. When the test caller is run,
|
|
that specific method will be run. This is not a useful thing to do,
|
|
however, as no diagnostics will be displayed.
|
|
One will normally use a \link ExecutingTest TestRunner \endlink (see below)
|
|
to display the results.
|
|
|
|
Once you have several tests, organize them into a suite.
|
|
|
|
|
|
|
|
|
|
|
|
\section suite Suite
|
|
|
|
How do you set up your tests so that you can run them all at once?
|
|
|
|
%CppUnit provides a \link CppUnit::TestSuite TestSuite \endlink class
|
|
that runs any number of TestCases together.
|
|
|
|
We saw, above, how to run a single test case.
|
|
|
|
To create a suite of two or more tests, you do the following:
|
|
|
|
\code
|
|
CppUnit::TestSuite suite;
|
|
CppUnit::TestResult result;
|
|
suite.addTest( new CppUnit::TestCaller<ComplexNumberTest>(
|
|
"testEquality",
|
|
&ComplexNumberTest::testEquality ) );
|
|
suite.addTest( new CppUnit::TestCaller<ComplexNumberTest>(
|
|
"testAddition",
|
|
&ComplexNumberTest::testAddition ) );
|
|
suite.run( &result );
|
|
\endcode
|
|
|
|
\link CppUnit::TestSuite TestSuites \endlink don't only have to
|
|
contain callers for TestCases. They can contain any object
|
|
that implements the \link CppUnit::Test Test \endlink interface.
|
|
For example, you can create a
|
|
\link CppUnit::TestSuite TestSuite \endlink in your code and
|
|
I can create one in mine, and we can run them together
|
|
by creating a \link CppUnit::TestSuite TestSuite \endlink
|
|
that contains both:
|
|
|
|
\code
|
|
CppUnit::TestSuite suite;
|
|
CppUnit::TestResult result;
|
|
suite.addTest( ComplexNumberTest::suite() );
|
|
suite.addTest( SurrealNumberTest::suite() );
|
|
suite.run( &result );
|
|
\endcode
|
|
|
|
|
|
|
|
|
|
\section test_runner TestRunner
|
|
|
|
How do you run your tests and collect their results?
|
|
|
|
Once you have a test suite, you'll want to run it. %CppUnit provides tools
|
|
to define the suite to be run and to display its results.
|
|
You make your suite accessible to a \link ExecutingTest TestRunner \endlink
|
|
program with a static method <I>suite</I> that returns a test suite.
|
|
|
|
For example, to make a ComplexNumberTest suite available to a
|
|
\link ExecutingTest TestRunner \endlink, add the following code to
|
|
ComplexNumberTest:
|
|
|
|
\code
|
|
public:
|
|
static CppUnit::TestSuite *suite()
|
|
{
|
|
CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite( "ComplexNumberTest" );
|
|
suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTest>(
|
|
"testEquality",
|
|
&ComplexNumberTest::testEquality ) );
|
|
suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTest>(
|
|
"testAddition",
|
|
&ComplexNumberTest::testAddition ) );
|
|
return suiteOfTests;
|
|
}
|
|
\endcode
|
|
|
|
\anchor test_runner_code
|
|
To use the text version, include the header files for the tests in Main.cpp:
|
|
|
|
\code
|
|
#include <cppunit/ui/text/TestRunner.h>
|
|
#include "ExampleTestCase.h"
|
|
#include "ComplexNumberTest.h"
|
|
\endcode
|
|
|
|
And add a call to
|
|
\link ::CppUnit::TextUi::TestRunner::addTest addTest(CppUnit::Test *) \endlink
|
|
in the <tt>main()</tt> function:
|
|
|
|
\code
|
|
int main( int argc, char **argv)
|
|
{
|
|
CppUnit::TextUi::TestRunner runner;
|
|
runner.addTest( ExampleTestCase::suite() );
|
|
runner.addTest( ComplexNumberTest::suite() );
|
|
runner.run();
|
|
return 0;
|
|
}
|
|
\endcode
|
|
|
|
The \link ExecutingTest TestRunner \endlink will run the tests.
|
|
If all the tests pass, you'll get an informative message.
|
|
If any fail, you'll get the following information:
|
|
|
|
- The name of the test case that failed
|
|
- The name of the source file that contains the test
|
|
- The line number where the failure occurred
|
|
- All of the text inside the call to CPPUNIT_ASSERT() which detected the failure
|
|
|
|
%CppUnit distinguishes between <I>failures</I> and <I>errors</I>. A failure is
|
|
anticipated and checked for with assertions. Errors are unanticipated problems
|
|
like division by zero and other exceptions thrown by the C++ runtime or your code.
|
|
|
|
|
|
|
|
|
|
\section helper_macros Helper Macros
|
|
|
|
As you might have noticed, implementing the fixture static <tt>suite()</tt>
|
|
method is a repetitive and error prone task. A \ref WritingTestFixture set of
|
|
macros have been created to automatically implements the
|
|
static <tt>suite()</tt> method.
|
|
|
|
The following code is a rewrite of ComplexNumberTest using those macros:
|
|
|
|
\code
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
class ComplexNumberTest : public CppUnit::TestFixture {
|
|
\endcode
|
|
First, we declare the suite, passing the class name to the macro:
|
|
\code
|
|
CPPUNIT_TEST_SUITE( ComplexNumberTest );
|
|
\endcode
|
|
The suite created by the static <tt>suite()</tt> method is named after
|
|
the class name.
|
|
Then, we declare each test case of the fixture:
|
|
\code
|
|
CPPUNIT_TEST( testEquality );
|
|
CPPUNIT_TEST( testAddition );
|
|
\endcode
|
|
Finally, we end the suite declaration:
|
|
\code
|
|
CPPUNIT_TEST_SUITE_END();
|
|
\endcode
|
|
At this point, a method with the following signature has been implemented:
|
|
\code
|
|
static CppUnit::TestSuite *suite();
|
|
\endcode
|
|
The rest of the fixture is left unchanged:
|
|
\code
|
|
private:
|
|
Complex *m_10_1, *m_1_1, *m_11_2;
|
|
public:
|
|
void setUp()
|
|
{
|
|
m_10_1 = new Complex( 10, 1 );
|
|
m_1_1 = new Complex( 1, 1 );
|
|
m_11_2 = new Complex( 11, 2 );
|
|
}
|
|
|
|
void tearDown()
|
|
{
|
|
delete m_10_1;
|
|
delete m_1_1;
|
|
delete m_11_2;
|
|
}
|
|
|
|
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 );
|
|
}
|
|
};
|
|
\endcode
|
|
|
|
The name of the \link CppUnit::TestCaller TestCaller \endlink added to the
|
|
suite are a composition of the fixture name and the method name.
|
|
|
|
In the present case, the names would be:
|
|
"ComplexNumberTest.testEquality" and "ComplexNumberTest.testAddition".
|
|
|
|
The \link WritingTestFixture helper macros \endlink help you write comon assertion.
|
|
For example, to check that ComplexNumber throws a MathException when dividing
|
|
a number by 0:
|
|
- add the test to the suite using CPPUNIT_TEST_EXCEPTION, specifying the expected
|
|
exception type.
|
|
- write the test case method
|
|
|
|
\code
|
|
CPPUNIT_TEST_SUITE( ComplexNumberTest );
|
|
// [...]
|
|
CPPUNIT_TEST_EXCEPTION( testDivideByZeroThrows, MathException );
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
// [...]
|
|
|
|
void testDivideByZeroThrows()
|
|
{
|
|
// The following line should throw a MathException.
|
|
*m_10_1 / ComplexNumber(0);
|
|
}
|
|
\endcode
|
|
|
|
If the expected exception is not thrown, then a assertion failure is reported.
|
|
|
|
|
|
|
|
|
|
\section test_factory_registry TestFactoryRegistry
|
|
|
|
The TestFactoryRegistry was created to solve two pitfalls:
|
|
- forgetting to add your fixture suite to the test runner (since it is in
|
|
another file, it is easy to forget)
|
|
- compilation bottleneck caused by the inclusion of all test case headers
|
|
(see \ref test_runner_code "previous example")
|
|
|
|
The TestFactoryRegistry is a place where suites can be registered at initialization
|
|
time.
|
|
|
|
To register the ComplexNumber suite, in the .cpp file, you add:
|
|
|
|
\code
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION( ComplexNumberTest );
|
|
\endcode
|
|
|
|
Behind the scene, a static variable type of
|
|
\link CppUnit::AutoRegisterSuite AutoRegisterSuite \endlink is declared.
|
|
On construction, it will
|
|
\link CppUnit::TestFactoryRegistry::registerFactory(TestFactory*) register \endlink
|
|
a \link CppUnit::TestSuiteFactory TestSuiteFactory \endlink into the
|
|
\link CppUnit::TestFactoryRegistry TestFactoryRegistry \endlink.
|
|
The \link CppUnit::TestSuiteFactory TestSuiteFactory \endlink returns
|
|
the \link CppUnit::TestSuite TestSuite \endlink returned by ComplexNumber::suite().
|
|
|
|
To run the tests, using the text test runner, we don't need to include the fixture
|
|
anymore:
|
|
|
|
\code
|
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
|
#include <cppunit/ui/text/TestRunner.h>
|
|
|
|
int main( int argc, char **argv)
|
|
{
|
|
CppUnit::TextUi::TestRunner runner;
|
|
\endcode
|
|
First, we retreive the instance of the
|
|
\link CppUnit::TestFactoryRegistry TestFactoryRegistry \endlink:
|
|
\code
|
|
CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
|
|
\endcode
|
|
Then, we obtain and add a new \link CppUnit::TestSuite TestSuite \endlink created
|
|
by the \link CppUnit::TestFactoryRegistry TestFactoryRegistry \endlink that
|
|
contains all the test suite registered using CPPUNIT_TEST_SUITE_REGISTRATION().
|
|
\code
|
|
runner.addTest( registry.makeTest() );
|
|
runner.run();
|
|
return 0;
|
|
}
|
|
\endcode
|
|
|
|
|
|
|
|
|
|
\section post_build_check Post-build check
|
|
|
|
Well, now that we have our unit tests running, how about integrating unit
|
|
testing to our build process ?
|
|
|
|
To do that, the application must returns a value different than 0 to indicate that
|
|
there was an error.
|
|
|
|
\link CppUnit::TextUi::TestRunner::run() TestRunner::run() \endlink returns
|
|
a boolean indicating if the run was successful.
|
|
|
|
Updating our main programm, we obtains:
|
|
\code
|
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
|
#include <cppunit/ui/text/TestRunner.h>
|
|
|
|
int main( int argc, char **argv)
|
|
{
|
|
CppUnit::TextUi::TestRunner runner;
|
|
CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
|
|
runner.addTest( registry.makeTest() );
|
|
bool wasSuccessful = runner.run( "", false );
|
|
return !wasSuccessful;
|
|
}
|
|
\endcode
|
|
|
|
Now, you need to run your application after compilation.
|
|
|
|
With Visual C++, this is done in <em>Project Settings/Post-Build step</em>,
|
|
by adding the following command: <tt>"$(TargetPath)"</tt>. It is expanded to
|
|
the application executable path. Look up the project
|
|
<tt>examples/cppunittest/CppUnitTestMain.dsp</tt> which
|
|
use that technic.
|
|
|
|
|
|
|
|
Original version by Michael Feathers.
|
|
Doxygen conversion and update by Baptiste Lepilleur.
|
|
*/
|