| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- /*! \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.
- */
|