CppTest  Version 2.0.0
Tutorial

Contents

Introduction

CppTest is a portable and powerful, yet simple, unit testing framework for handling automated tests in C++. The focus lies on usability and extendability. Several output formats are supported and new ones are easily added.

This tutorial is intended to quickly get you started.

CppTest is released under the GNU Lesser General Public License.

Tests

Test cases

Each test must be created and run within a test suite (see Test suites below), which must be derived from Test::Suite. Tests must be registered with the TEST_ADD(func) macro inorder to be executed. Note that a test function must return void and take no parameters. For example:

class ExampleTestSuite : public Test::Suite
{
public:
ExampleTestSuite()
{
TEST_ADD(ExampleTestSuite::first_test)
TEST_ADD(ExampleTestSuite::second_test)
}
private:
void first_test();
void second_test();
};

Asserts

Asserts are used to ensure that the tests are correct. If not, one or more asserts will be generated. There exist several types of asserts, see Available asserts for a complete list.

For example, the functions declared within ExampleTestSuite may be declared as:

void ExampleTestSuite::first_test()
{
// Will succeed since the expression evaluates to true
//
TEST_ASSERT(1 + 1 == 2)
// Will fail since the expression evaluates to false
//
TEST_ASSERT(0 == 1);
}
void ExampleTestSuite::second_test()
{
// Will succeed since the expression evaluates to true
//
TEST_ASSERT_DELTA(0.5, 0.7, 0.3);
// Will fail since the expression evaluates to false
//
TEST_ASSERT_DELTA(0.5, 0.7, 0.1);
}

Output handlers

Available output handlers

An output handler takes care of all assert messages and generates some output as result. There exist several output handlers that all fit different needs. Currently, the following output handlers exist:

New output handlers should be derived from Test::Output.

Screenshots

The result from the different output handlers is shown below:

Test suites

Running test suites

The tests within a test suite are all executed when Test::Suite::run() is called. This method returns a boolean value that only returns true if all tests were successful. This value may be used to return a suiteable value from the program. For example, the following is required to execute our tests within ExampleTestSuite:

ExampleTestSuite ets;
return ets.run(output) ? EXIT_SUCCESS : EXIT_FAILURE;

Note that a single test normally continues after an assert. However, this behavior may be changed with an optional parameter to Test::Suite::run(). For example:

class SomeTestSuite: public Test::Suite
{
public:
SomeTestSuite() { TEST_ADD(SomeTestSuite::test) }
private:
void test()
{
TEST_FAIL("this will always fail")
TEST_FAIL("this assert will never be executed")
}
};
bool run_tests()
{
SomeTestSuite sts;
return sts.run(output, false); // Note the 'false' parameter
}

Embedded test suites

Test suites may also be added other test suites using Test::Suite::add(). This way, you may develop logically separated test suites and run all tests at once. For example:

class TestSuite1: public Test::Suite { }; // ... with many tests
class TestSuite2: public Test::Suite { }; // ... with many tests
class TestSuite3: public Test::Suite { }; // ... with many tests
bool run_tests()
{
ts.add(unique_ptr<Test::Suite>(new TestSuite1));
ts.add(unique_ptr<Test::Suite>(new TestSuite2));
ts.add(unique_ptr<Test::Suite>(new TestSuite3));
return ts.run(output);
}

Test fixtures

Test cases in the same test suite often share the same requirements, they all require some known set of objects or resources. Instead of repeating all initialization code for each test it may be moved to the Test::Suite::setup() and Test::Suite::tear_down() functions. The setup function is called before each test function is called, and the tear down function is called after each test function has been called. For example:

class SomeTestSuite: public Test::Suite
{
public:
SomeTestSuite()
{
TEST_ADD(SomeTestSuite::test1)
TEST_ADD(SomeTestSuite::test2)
}
protected:
virtual void setup() {} // setup resources...
virtual void tear_down() {} // remove resources...
private:
void test1() {} // use common resources...
void test2() {} // use common resources...
};