DGtal  0.9.3beta
Unit test in DGtal using Catch

Table of Contents

Author(s) of this documentation:
David Coeurjolly


Catch Is a C++ framework to help unit test design. More precisely, thanks to couple of C++ macros, Catch enabled unit test are easy to write and easy to review.

In this documentation page, we just describe how to write such test files in DGtal. For a complete documentation of Catch, please refer to Catch.

Catch in DGtal

We illustrate here basic Catch usages using some tests on the PointVector class.

First of all, all test files must include the following header:

#include "DGtalCatch.h"

Once this header included, there is no need to create a main() function in your cpp file, everything is handled automatically.

Unit tests are decomposed into TEST_CASE and SECTION in a test case. For example, the following code performs some tests on the PointVector class (see exampleCatch.cpp for details).

TEST_CASE( "Point Vector Unit tests" )
//Global variables and init for this test case
typedef PointVector<4, DGtal::int32_t> Point;
typedef PointVector<4, double> RealPoint;
DGtal::int32_t t1[] = {1,2,3,4};
DGtal::int32_t t2[]= {5,4,3,2};
double t3[]= {1.0,-1.0,2.0,-2.0};
Point p1( t1 );
Point p1bis( t1 );
Point p2( t2 );
RealPoint p3(t3);
REQUIRE( (p1 == p1bis) );
REQUIRE( p1 < p2 );
SECTION("Min/Max of vector components")
REQUIRE( (p3.max() == 2.0) );
REQUIRE( (p3.min() == -2.0) );
REQUIRE( (*p3.maxElement() == 2.0) );
REQUIRE( (*p3.minElement() == -2.0) );
SECTION("Arithmetical Operators")
REQUIRE( ((p1 + p2) == Point(6,6,6,6)) );
REQUIRE( ((p1 - p2) == Point(-4,-2,0,2)) );
REQUIRE( ((p1*2) == Point(2,4,6,8)) );
REQUIRE( ((2*p1) == Point(2,4,6,8)) );
REQUIRE( ((-p1) == Point(-1,-2,-3,-4)) );
REQUIRE( (p1.inf(p2) == Point(1,2,3,2)) );
REQUIRE( (p1.sup(p2) == Point(5,4,3,4)) );
REQUIRE( (p1.dot(p2) == 30) );

When compiling this simple test, the executable handles several commandline options. For example


runs all test cases and sections.

./exampleCatch -s

runs all tests with detailed messages

./exampleCatch -d yes

runs all tests with timings for each section.

./exampleCatch --help

displays all command-line options.

Please have a look to Catch for further macros and comments. For instance, tags can be associated with sections and test cases allowing to only run specific tests.

Advanced usages

In Catch, experimental macros exist to describe templated tests. For instance, the following code tests some STL containers.

TEMPLATE_TEST_CASE_3("STL Container test", "Description", T,
std::list<int>, std::vector<int>, std::set<int>)
T defaultConstructed;
SECTION("Size of the default constructed container")
REQUIRE( ( defaultConstructed.size() == 0 ) );
//Adding a value
defaultConstructed.insert( defaultConstructed.begin(), 5 );
SECTION("Size after one insert")
REQUIRE( ( defaultConstructed.size() == 1 ) );

In this example, 6 test sections are automatically generated. The resulting output (with timings) is:

./exampleCatch "STL Container test" -d yes
Size of the default constructed container completed in 3.3e-05s
std::list<int> completed in 0.000124s
STL Container test completed in 0.0002s
Size after one insert completed in 9e-06s
std::list<int> completed in 3.5e-05s
STL Container test completed in 7.7e-05s
Size of the default constructed container completed in 1.5e-05s
std::vector<int> completed in 8.4e-05s
STL Container test completed in 0.000133s
Size after one insert completed in 1.2e-05s
std::vector<int> completed in 5.2e-05s
STL Container test completed in 0.000112s
Size of the default constructed container completed in 1e-05s
std::set<int> completed in 7.2e-05s
STL Container test completed in 0.000134s
Size after one insert completed in 1.5e-05s
std::set<int> completed in 5.7e-05s
STL Container test completed in 0.000116s
In the current Catch version, the number of templated types must be specified explicitly in the macro name (up to 8 templated types per test case).