Differences between revisions 11 and 26 (spanning 15 versions)
Revision 11 as of 2008-12-15 16:40:53
Size: 7852
Editor: mpiat1403
Comment: Added missing includes
Revision 26 as of 2008-12-17 12:00:29
Size: 12822
Editor: mpiat1403
Comment: setup()/tearDown() called before and after every test, resp.
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
This document describes very shortly how to install the [http://sourceforge.net/projects/cppunit/ CppUnit] framework under Unix and how to write and run a very simplistic test case. This should get you started with using Cpp``Unit, so that you can follow and try out the examples given in the [http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html CppUnit CookBook]. '''Index'''
[[TableOfContents]]

= About this document =

This document describes in brief how to install the [http://sourceforge.net/projects/cppunit/ CppUnit] framework under Unix and how to write and run test programs with it. This should get you started with using Cpp``Unit.

The document is based on the [http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html CppUnit CookBook]. The examples and many explanations are taken almost verbatim from there, slightly changed and improved for readability.


= References =

The project's homepage is http://sourceforge.net/projects/cppunit.

The latest Doxygen documentation of the project's class hierarchy is http://cppunit.sourceforge.net/doc/lastest/index.html. This may be useful while you read this document.
Line 5: Line 19:
Download the latest version of Cpp``Unit from Download the latest version of Cpp``Unit from http://sourceforge.net/projects/cppunit. At the time of this writing, it is
Line 28: Line 42:
// files Complex.h/Complex.cpp // file Complex.h
Line 37: Line 51:
}}}

{{{
// file Complex.cpp

#include "Complex.h"
Line 51: Line 71:
Now let us write a Cpp``Unit test case for this class:

{{{
// file ComplexNumberTest.h/.cpp
Now let us write a Cpp``Unit test case for this class.

For this, we have to subclass the `TestCase` class and to override the method `runTest()`. To check a value, we call `CPPUNIT_ASSERT(bool)` and pass in an expression that is true if the test succeeds.


{{{
// file ComplexNumberTest.h
Line 57: Line 80:
#include "Complex.h"
Line 61: Line 83:
  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)) );
    CPPUNIT_ASSERT( Complex (1, 2) + Complex(3, 4) == Complex (4, 6));
  }
  ComplexNumberTest( std::string name );
  void runTest();
Line 70: Line 87:


{{{
// file ComplexNumberTest.cpp

#include "Complex.h"
#include "ComplexNumberTest.h"

ComplexNumberTest::ComplexNumberTest( std::string name ) : CppUnit::TestCase( name ) {}

void ComplexNumberTest::runTest() {
  CPPUNIT_ASSERT( Complex (10, 1) == Complex (10, 1) );
  CPPUNIT_ASSERT( !(Complex (1, 1) == Complex (2, 2)) );
  CPPUNIT_ASSERT( Complex (1, 2) + Complex(3, 4) == Complex (4, 6));
}
}}}



The main program creates a `TestCase` object and calls its `runTest()` method:
Line 85: Line 122:
For this, we have to subclass the `TestCase` class and to override the method `runTest()`. To check a value, we call `CPPUNIT_ASSERT(bool)` and pass in an expression that is true if the test succeeds.
Line 90: Line 126:
Suppose we put all the above code into one file `ComplexNumberTest.cpp`. Then the following makefile will do the job for us: The following makefile based on implicit rules will do the job for us:
Line 97: Line 133:
# Implicit rule: How to make an executable from a .cpp-file
%: %.cpp
 ${CC} -o $@ $< ${CXXFLAGS} ${INCLS} ${LIBDIRS} ${LIBS}
# Implicit rule: How to make an .o-file from a .cpp-file
%.o: %.cpp
 ${CXX} -c $< ${CXXFLAGS} ${INCLS}

# Implicit rule: How to make an executable from .o-files
%: %.o
 ${CXX} -o $@ $^ ${LIBDIRS} ${LIBS}

runComplexNumberTest: runComplexNumberTest.o ComplexNumberTest.o Complex.o
Line 103: Line 145:
Line 112: Line 153:
cc -o ComplexNumberTest ComplexNumberTest.cpp -I/var/tmp/cppunit/install/include/ -L/var/tmp/cppunit/install/lib -lcppunit -ldl
export LD_LIBRARY_PATH=/var/tmp/cppunit/install/lib && ./ComplexNumberTest
cc -c runComplexNumberTest.cpp -Wall -I/var/tmp/cppunit/install/include/
cc -c ComplexNumberTest.cpp -Wall -I/var/tmp/cppunit/install/include/
cc -c Complex.cpp -Wall -I/var/tmp/cppunit/install/include/
cc -o runComplexNumberTest runComplexNumberTest.o ComplexNumberTest.o Complex.o -L/var/tmp/cppunit/install/lib -lcppunit -ldl
export LD_LIBRARY_PATH=/var/tmp/cppunit/install/lib && ./runComplexNumberTest
Line 118: Line 162:
/bin/sh: line 1:  1457 Aborted ./ComplexNumberTest /bin/sh: line 1: 10793 Aborted ./runComplexNumberTest
make: *** [runtest] Error 134
Line 126: Line 171:
Now go on and read the rest of the [http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html CppUnit CookBook] and try out the examples given there. You will learn about Test``Fixtures, Test``Callers, Test``Suites, and Test``Runners. That was a very simple test. Ordinarily, we will have many little test cases that we will want to run on the same set of objects. To do this, we can use a "fixture".

Now you should maybe skim through the [http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html CppUnit CookBook]. You will learn about Test``Fixtures, Test``Callers, Test``Suites, and Test``Runners.
Line 130: Line 177:
 * A `TestFixture` is a set of objects that serves as a base for a set of test cases, together with methods that implement these test cases.  * A `TestFixture` is a set of objects that serves as a base for a set of test cases, together with methods that implement these test cases. A `TestFixture` is used to provide a common environment for a set of test cases. Each test runs in its own fixture so there can be no side effects among test runs.
Line 138: Line 185:
Here is a complete program:

{{{
// files ComplexNumberTestSuite.h/.cpp

// A test suite for Complex, run by a runner
In a fixture, we can

 * Add member variables for each part of the fixture
 * Override setUp() to initialize the variables
 * Override tearDown() to release any permanent resources we allocated in setUp()

Here is a test fixture for our `Complex` class. It allocates three `Complex` objects to be used in its test cases. It implements two test cases, `testEquality()` and `testAddition()`. It overrides the `suite()` method to create and return a test suite consisting of its two test cases.

`setup()` and `tearDown()` are called ''before'' and ''after'' every test case in the fixture, respectively.

{{{
// file ComplexNumberTestFixture.h

// A test fixture for Complex, returning a test suite to be run by a runner
Line 151: Line 206:
class ComplexNumberTest : public CppUnit::TestFixture { class ComplexNumberTestFixture : public CppUnit::TestFixture {
Line 155: Line 210:
  void setUp()
  {
    a = new Complex( 1, 2 );
    b = new Complex( 3, 4 );
    s = new Complex( 4, 6 );
  }

  void tearDown()
  {
    delete a;
    delete b;
    delete s;
  }

  void testEquality()
  {
    CPPUNIT_ASSERT( *a == *a );
    CPPUNIT_ASSERT( !(*a == *b) );
  }

  void testAddition()
  {
    CPPUNIT_ASSERT( *a + *b == *s );
  }

  static CppUnit::Test *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;
  }
  void setUp();
  void tearDown();

  void testEquality();
  void testAddition();

  static CppUnit::Test* suite();
Line 196: Line 221:
// file ComplexNumberTestFixture.cpp

#include "ComplexNumberTestFixture.h"

void ComplexNumberTestFixture::setUp()
{
  a = new Complex( 1, 2 );
  b = new Complex( 3, 4 );
  s = new Complex( 4, 6 );
}

void ComplexNumberTestFixture::tearDown()
{
  delete a;
  delete b;
  delete s;
}

void ComplexNumberTestFixture::testEquality()
{
  CPPUNIT_ASSERT( *a == *a );
  CPPUNIT_ASSERT( !(*a == *b) );
}

void ComplexNumberTestFixture::testAddition()
{
  CPPUNIT_ASSERT( *a + *b == *s );
}

CppUnit::Test* ComplexNumberTestFixture::suite()
{
  CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite( "ComplexNumberTest" );
  
  suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTestFixture>(
    "testEquality",
    &ComplexNumberTestFixture::testEquality ) );
  suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTestFixture>(
    "testAddition",
    &ComplexNumberTestFixture::testAddition ) );
  return suiteOfTests;
}
}}}

To run test the suite returned by the fixture's `suite()` method, we pass it to a `TestRunner` object and call its `run()` methdod:

{{{
Line 199: Line 270:
#include "ComplexNumberTestSuite.h" #include "ComplexNumberTestFixture.h"
Line 204: Line 275:
  runner.addTest( ComplexNumberTest::suite() );   runner.addTest( ComplexNumberTestFixture::suite() );
Line 207: Line 278:
  // and maybe add more suites
Line 229: Line 301:
1) test: testAddition (F) line: 56 ComplexNumberTestSuite.cpp 1) test: testAddition (F) line: 27 ComplexNumberTestFixture.cpp
Line 239: Line 311:
The following code is a rewrite of `ComplexNumberTest` using these macros:

{{{
// file ComplexNumberTestWithMacro.h/.cpp
The following code is a rewrite of `ComplexNumberTestFixture` using these macros:

{{{
// file ComplexNumberTestFixturewithMacro.h

// A test fixture for Complex, returning a test suite to be run by a runner

#include <cppunit/TestFixture
.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h>
Line 248: Line 326:
class ComplexNumberTestWithMacro : public CppUnit::TestFixture {

CPPUNIT_TEST_SUITE( ComplexNumberTestWithMacro );
class ComplexNumberTestFixtureWithMacro : public CppUnit::TestFixture {

CPPUNIT_TEST_SUITE( ComplexNumberTestFixtureWithMacro );
Line 255: Line 333:
// remainder as in the class above // remainder as in the class above, but without suite()
Line 260: Line 338:
  void setUp()
  {
    a = new Complex( 1, 2 );
    b = new Complex( 3, 4 );
    s = new Complex( 4, 6 );
  }

  void tearDown()
  {
    delete a;
    delete b;
    delete s;
  }

  void testEquality()
  {
    CPPUNIT_ASSERT( *a == *a );
    CPPUNIT_ASSERT( !(*a == *b) );
  }

  void testAddition()
  {
    CPPUNIT_ASSERT( *a + *b == *s );
  }
  void setUp();
  void tearDown();

  void testEquality();
  void testAddition();
Line 285: Line 344:
}}}

// of course, the implementation of suite() is also missing in the .cpp file ;-)
}}}
Line 289: Line 349:


= Test factory registry =

It is easy to forget to add a fixture suite to the test runner since it is in another file.

Compilation bottleneck may be caused by the inclusion of all test case headers.

To solve these problems, Cpp``Unit introduced `TestFactoryRegistry` objects. Such an object is a place where suites can be registered at initialization time.

For example, to register the `ComplexNumberTestFixture` suite in the registry, we would add 2 lines in the .cpp file:

{{{
// file ComplexNumberTestFixture.cpp

#include <cppunit/extensions/HelperMacros.h>
#include "ComplexNumberTestFixture.h"

CPPUNIT_TEST_SUITE_REGISTRATION( ComplexNumberTestFixture );

// now as before...
}}}


Then, to run the tests using the text test runner, we do not need to include the fixture anymore:

{{{
// file runTestSuiteWithTestFactoryRegistry.cpp

#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>

int main()
{
  CppUnit::TextUi::TestRunner runner;
  CppUnit::TestFactoryRegistry &registry
       = CppUnit::TestFactoryRegistry::getRegistry();
  runner.addTest( registry.makeTest() );
  runner.run();
}
}}}

That is, first we retrieve the instance of the `TestFactoryRegistry`. Then we obtain and add a new `TestSuite` created by the `TestFactoryRegistry` that contains all the test suites registered using `CPPUNIT_TEST_SUITE_REGISTRATION()`.

You may wonder from where the runner now knows what tests to add: This is specified by simply linking the `ComplexNumberTestFixture.o` object file to the main object file `runTestSuiteWithTestFactoryRegistry.o`.



= Automated post-build checks =

How do we integrate unit testing to our build process? `TestRunner::run()` returns a boolean indicating wether the run was successful. We can just return this value from `main()`:

{{{
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>

int main()
{
  CppUnit::TextUi::TestRunner runner;
  CppUnit::TestFactoryRegistry &registry
       = CppUnit::TestFactoryRegistry::getRegistry();
  runner.addTest( registry.makeTest() );
  bool wasSuccessful = runner.run( "", false );
  return wasSuccessful ? 0 : 1;
}
}}}

Now, we can run our test program after each compilation of our tested application. This can be formulated by an additional command in the makefile. If there is an error (the exit status is nonzero), the `make` utility gives up on the current rule, and perhaps on all rules.

Index TableOfContents

About this document

This document describes in brief how to install the [http://sourceforge.net/projects/cppunit/ CppUnit] framework under Unix and how to write and run test programs with it. This should get you started with using CppUnit.

The document is based on the [http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html CppUnit CookBook]. The examples and many explanations are taken almost verbatim from there, slightly changed and improved for readability.

References

The project's homepage is http://sourceforge.net/projects/cppunit.

The latest Doxygen documentation of the project's class hierarchy is http://cppunit.sourceforge.net/doc/lastest/index.html. This may be useful while you read this document.

Installing

Download the latest version of CppUnit from http://sourceforge.net/projects/cppunit. At the time of this writing, it is http://downloads.sourceforge.net/cppunit/cppunit-1.12.1.tar.gz.

Let us install it under /var/tmp/cppunit/install:

$ cd /var/tmp/
$ mv ~/cppunit-1.12.1.tar.gz .
$ tar xzf cppunit-1.12.1.tar.gz
$ ln -s cppunit-1.12.1 cppunit
$ cd cppunit
$ ./configure --prefix=`pwd`/install
$ make
$ make check
$ make install

Writing a simplistic test case

Suppose we are developing a class Complex for dealing with complex numbers. In the following code, the operator+ intentionally contains a bug:

// file Complex.h

class Complex { 
  friend bool   operator==(const Complex& a, const Complex& b);
  friend Complex operator+(const Complex& a, const Complex& b);
  double real, imaginary;
public:
  Complex( double r, double i = 0 )  : real(r), imaginary(i) {}
};

// file Complex.cpp

#include "Complex.h"

bool operator==( const Complex &a, const Complex &b )
{ 
  return a.real == b.real  &&  a.imaginary == b.imaginary; 
}

Complex operator+( const Complex &a, const Complex &b )
{ 
  // BUG! imaginary part should be 'a.imaginary + b.imaginary'
  return Complex(a.real + b.real, a.imaginary + b.real); 
}

Now let us write a CppUnit test case for this class.

For this, we have to subclass the TestCase class and to override the method runTest(). To check a value, we call CPPUNIT_ASSERT(bool) and pass in an expression that is true if the test succeeds.

// file ComplexNumberTest.h

#include <cppunit/TestCase.h>

class ComplexNumberTest : public CppUnit::TestCase { 
public: 
  ComplexNumberTest( std::string name );
  void runTest(); 
};

// file ComplexNumberTest.cpp

#include "Complex.h"
#include "ComplexNumberTest.h"

ComplexNumberTest::ComplexNumberTest( std::string name ) : CppUnit::TestCase( name ) {}

void ComplexNumberTest::runTest() {
  CPPUNIT_ASSERT( Complex (10, 1) == Complex (10, 1) );
  CPPUNIT_ASSERT( !(Complex (1, 1) == Complex (2, 2)) );
  CPPUNIT_ASSERT( Complex (1, 2) + Complex(3, 4) == Complex (4, 6));
}

The main program creates a TestCase object and calls its runTest() method:

// file runComplexNumberTest.cpp

#include "ComplexNumberTest.h"

int main()
{
  ComplexNumberTest myTest("My first CppUnit test");
  
  myTest.runTest();
}

Compiling and running

The following makefile based on implicit rules will do the job for us:

INCLS   = -I/var/tmp/cppunit/install/include/
LIBDIRS = -L/var/tmp/cppunit/install/lib
LIBS    = -lcppunit -ldl # note that CppUnit needs libld.so!

# Implicit rule: How to make an .o-file from a .cpp-file
%.o: %.cpp
        ${CXX} -c $< ${CXXFLAGS} ${INCLS}

# Implicit rule: How to make an executable from .o-files
%: %.o
        ${CXX} -o $@ $^ ${LIBDIRS} ${LIBS}

runComplexNumberTest: runComplexNumberTest.o ComplexNumberTest.o Complex.o

runtest: runComplexNumberTest
        export LD_LIBRARY_PATH=/var/tmp/cppunit/install/lib && ./runComplexNumberTest

Note that CppUnit needs the library ld.so in the linking step.

Now we can compile and run the program:

$ make runtest
cc -c runComplexNumberTest.cpp -Wall -I/var/tmp/cppunit/install/include/
cc -c ComplexNumberTest.cpp -Wall -I/var/tmp/cppunit/install/include/
cc -c Complex.cpp -Wall -I/var/tmp/cppunit/install/include/
cc -o runComplexNumberTest runComplexNumberTest.o ComplexNumberTest.o Complex.o -L/var/tmp/cppunit/install/lib -lcppunit -ldl
export LD_LIBRARY_PATH=/var/tmp/cppunit/install/lib && ./runComplexNumberTest
terminate called after throwing an instance of 'CppUnit::Exception'
  what():  assertion failed
- Expression: Complex (1, 2) + Complex(3, 4) == Complex (4, 6)

/bin/sh: line 1: 10793 Aborted                 ./runComplexNumberTest
make: *** [runtest] Error 134

As we can see, the third assertion failed, which detects the bug in our operator+.

Fixtures, Callers, Suites, and Runners

That was a very simple test. Ordinarily, we will have many little test cases that we will want to run on the same set of objects. To do this, we can use a "fixture".

Now you should maybe skim through the [http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html CppUnit CookBook]. You will learn about TestFixtures, TestCallers, TestSuites, and TestRunners.

In short:

  • A TestFixture is a set of objects that serves as a base for a set of test cases, together with methods that implement these test cases. A TestFixture is used to provide a common environment for a set of test cases. Each test runs in its own fixture so there can be no side effects among test runs.

  • A TestCaller runs a particular method (test case) of a fixture.

  • A TestSuite runs any number of callers together.

  • A TestRunner runs a suite and displays its results.

In a fixture, we can

  • Add member variables for each part of the fixture
  • Override setUp() to initialize the variables
  • Override tearDown() to release any permanent resources we allocated in setUp()

Here is a test fixture for our Complex class. It allocates three Complex objects to be used in its test cases. It implements two test cases, testEquality() and testAddition(). It overrides the suite() method to create and return a test suite consisting of its two test cases.

setup() and tearDown() are called before and after every test case in the fixture, respectively.

// file ComplexNumberTestFixture.h

// A test fixture for Complex, returning a test suite to be run by a runner

#include <cppunit/TestFixture.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h>

#include "Complex.h"

class ComplexNumberTestFixture : public CppUnit::TestFixture  {
private:
  Complex *a, *b, *s;
public:
  void setUp();
  void tearDown();

  void testEquality();
  void testAddition();

  static CppUnit::Test* suite();
};

// file ComplexNumberTestFixture.cpp

#include "ComplexNumberTestFixture.h"

void ComplexNumberTestFixture::setUp()
{
  a = new Complex( 1, 2 );
  b = new Complex( 3, 4 );
  s = new Complex( 4, 6 );  
}

void ComplexNumberTestFixture::tearDown() 
{
  delete a;
  delete b;
  delete s;
}

void ComplexNumberTestFixture::testEquality()
{
  CPPUNIT_ASSERT( *a == *a );
  CPPUNIT_ASSERT( !(*a == *b) );
}

void ComplexNumberTestFixture::testAddition()
{
  CPPUNIT_ASSERT( *a + *b == *s );
}

CppUnit::Test* ComplexNumberTestFixture::suite()
{
  CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite( "ComplexNumberTest" );
  
  suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTestFixture>( 
                                "testEquality", 
                                &ComplexNumberTestFixture::testEquality ) );
  suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTestFixture>(
                                "testAddition",
                                &ComplexNumberTestFixture::testAddition ) );
  return suiteOfTests;
}

To run test the suite returned by the fixture's suite() method, we pass it to a TestRunner object and call its run() methdod:

// file runTestSuite.cpp

#include <cppunit/ui/text/TestRunner.h>
#include "ComplexNumberTestFixture.h"

int main()
{
  CppUnit::TextUi::TestRunner runner;
  runner.addTest( ComplexNumberTestFixture::suite() );
  //runner.addTest( AnotherTestFixture::suite() );
  //runner.addTest( AnExampleTestCase::suite() );
  // and maybe add more suites
  runner.run();
}

The TestRunner will run the tests. If all the tests pass, we shall get an informative message. If any fail, we shall 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

The output of the above program is

..F


!!!FAILURES!!!
Test Results:
Run:  2   Failures: 1   Errors: 0


1) test: testAddition (F) line: 27 ComplexNumberTestFixture.cpp
assertion failed
- Expression: *a + *b == *s

Helper macros

Implementing the static suite() method in a TestFixture is a repetitive and error prone task. A set of macros have been created to automatically implement this method.

The following code is a rewrite of ComplexNumberTestFixture using these macros:

// file ComplexNumberTestFixturewithMacro.h

// A test fixture for Complex, returning a test suite to be run by a runner

#include <cppunit/TestFixture.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h>

#include <cppunit/extensions/HelperMacros.h>

#include "Complex.h"

class ComplexNumberTestFixtureWithMacro : public CppUnit::TestFixture  {

CPPUNIT_TEST_SUITE( ComplexNumberTestFixtureWithMacro );
CPPUNIT_TEST( testEquality ); 
CPPUNIT_TEST( testAddition );
CPPUNIT_TEST_SUITE_END(); 

// remainder as in the class above, but without suite()

private:
  Complex *a, *b, *s;
public:
  void setUp();
  void tearDown();

  void testEquality();
  void testAddition();
};

// of course, the implementation of suite() is also missing in the .cpp file ;-)

There are other helper macros, for example, to check that a specific exception is thrown under specific circumstances. Check the documentation.

Test factory registry

It is easy to forget to add a fixture suite to the test runner since it is in another file.

Compilation bottleneck may be caused by the inclusion of all test case headers.

To solve these problems, CppUnit introduced TestFactoryRegistry objects. Such an object is a place where suites can be registered at initialization time.

For example, to register the ComplexNumberTestFixture suite in the registry, we would add 2 lines in the .cpp file:

// file ComplexNumberTestFixture.cpp

#include <cppunit/extensions/HelperMacros.h> 
#include "ComplexNumberTestFixture.h"

CPPUNIT_TEST_SUITE_REGISTRATION( ComplexNumberTestFixture ); 

// now as before...

Then, to run the tests using the text test runner, we do not need to include the fixture anymore:

// file runTestSuiteWithTestFactoryRegistry.cpp

#include <cppunit/extensions/TestFactoryRegistry.h> 
#include <cppunit/ui/text/TestRunner.h> 

int main() 
{ 
  CppUnit::TextUi::TestRunner runner;
  CppUnit::TestFactoryRegistry &registry 
       = CppUnit::TestFactoryRegistry::getRegistry();
  runner.addTest( registry.makeTest() ); 
  runner.run(); 
} 

That is, first we retrieve the instance of the TestFactoryRegistry. Then we obtain and add a new TestSuite created by the TestFactoryRegistry that contains all the test suites registered using CPPUNIT_TEST_SUITE_REGISTRATION().

You may wonder from where the runner now knows what tests to add: This is specified by simply linking the ComplexNumberTestFixture.o object file to the main object file runTestSuiteWithTestFactoryRegistry.o.

Automated post-build checks

How do we integrate unit testing to our build process? TestRunner::run() returns a boolean indicating wether the run was successful. We can just return this value from main():

#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>

int main()
{
  CppUnit::TextUi::TestRunner runner;
  CppUnit::TestFactoryRegistry &registry 
       = CppUnit::TestFactoryRegistry::getRegistry();
  runner.addTest( registry.makeTest() );
  bool wasSuccessful = runner.run( "", false );
  return wasSuccessful ? 0 : 1;
}

Now, we can run our test program after each compilation of our tested application. This can be formulated by an additional command in the makefile. If there is an error (the exit status is nonzero), the make utility gives up on the current rule, and perhaps on all rules.

CompleteSearch: completesearch/InstallingAndRunningCppUnit (last edited 2008-12-17 12:00:29 by mpiat1403)