Home > The Unit Test Framework > User's guide > Test organization > Test case template > Manual registration
PrevNext

Manually registered test case template

One way to perform the same set of checks for a component instantiated with different template parameters is illustrated in the following example:

template <typename T>
void single_test()
{
    BOOST_CHECK( /* test assertion */ );
}

void combined_test()
{
    single_test<int>();
    single_test<float>();
    single_test<unsigned char>();
}

There several problems/inconveniencies with above approach, including:

Ideally the test case template would be based on nullary function template (like single_test above). Unfortunately function templates are neither addressable nor can be used as template parameters. To alleviate the issue the manually registered test case template facility consists of two co-working macros: BOOST_TEST_CASE_TEMPLATE_FUNCTION and BOOST_TEST_CASE_TEMPLATE. Former is used to define the test case template body, later - to create and register test cases based on it.

The macro BOOST_TEST_CASE_TEMPLATE_FUNCTION requires two arguments: the name of the test case template and the name of the format type parameter:

BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_case_name, type_name)
BOOST_TEST_CASE_TEMPLATE_FUNCTION( test_case_name, type_name )
{
  // test case template body
}

The macro BOOST_TEST_CASE_TEMPLATE_FUNCTION is intended to be used in place of nullary function template signature:

template<typename type_name>
void
test_case_name()
{
  // test case template body
}

The only difference is that the BOOST_TEST_CASE_TEMPLATE_FUNCTION makes the test case template name usable in the template argument list.

BOOST_TEST_CASE_TEMPLATE requires two arguments: the name of the test case template and Boost.MPL compatible collection of types to instantiate it with. The names passed to both macros should be the same.

BOOST_TEST_CASE_TEMPLATE(test_case_name, collection_of_types)

BOOST_TEST_CASE_TEMPLATE creates an instance of the test case generator. When passed to the method test_suite::add, the generator produces a separate sub test case for each type in the supplied collection of types and registers it immediately in the test suite. Each test case is based on the test case template body instantiated with a particular test type.

Sub test case names are deduced from the macro argument test_case_name. If you prefer to assign different test case names, you need to use the underlying make_test_case interface instead. Both test cases creation and registration is performed in the test module initialization function.

The test case template facility is preferable to the approach in example above, since execution of each sub test case is guarded and counted separately. It produces a better test log/results report (in example above in case of failure you can't say which type is at fault) and allows you to test all types even if one of them causes termination of the sub test case.

Example 13. Manually registered test case template

#include <boost/test/included/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
using namespace boost::unit_test;

//____________________________________________________________________________//

BOOST_TEST_CASE_TEMPLATE_FUNCTION( my_test, T )
{
    BOOST_CHECK_EQUAL( sizeof(T), 4 );
}

//____________________________________________________________________________//

test_suite*
init_unit_test_suite( int argc, char* argv[] )
{
    typedef boost::mpl::list<int,long,unsigned char> test_types;

    framework::master_test_suite().
        add( BOOST_TEST_CASE_TEMPLATE( my_test, test_types ) );

    return 0;
}

//____________________________________________________________________________//
Source code | Show output
> example
Running 3 test cases...
test.cpp(10): error in "my_test<unsigned char>": check sizeof(T) == 4 failed [1 != 4]

*** 1 failure detected in test suite "Master Test Suite"


PrevUpHomeNext