Unit testing with Boost.Test

The Boost Test library provides tools to setup, organize, run and analyze fine grained tests of your C/C++ code. The official documentation is quite heavy. A very nice introduction can be found at alittlemadness.com.

Here we provide instructions how to use Boost.Test in your LHCb projects.

Setting up Boost.Test using CMT

Your tests will live in a (potentially several) C/C++ application and link to the boost.test library that comes with the LHCb software. In order to build the test application you need to add the following lines to the requirements file in the cmt/ directory of your package.

application       utestExample     ../src/utestExample.cxx
macro_append Boost_linkopts " -lboost_unit_test_framework-${Boost_compiler_version}-mt-${Boost_file_version}" 

of course you can rename utestExample.cxx to whatever suits you and you can have several test applications if you like.

The next section shows a few examples of how to write a test application utestExample.cxx

Writing fine grained tests with Boost.Test

Basic testing

Here is a simple example for a test application:

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE utestExample
#include <boost/test/unit_test.hpp>
#include "MyExampleClass.h"
///-------- Basic Test: can we instantiate an object and call a method? ---
/// lets say MyExampleClass implements an add() function

double addtest(double x, double y){
  MyExampleClass adder;
  return adder.add(x,y);
} // end addtest

/// le's use this function in a test case:
BOOST_AUTO_TEST_CASE(adderTest){
   BOOST_CHECK(addtest(3,2) == 4);
}

Note the names utestExample for the test module and adderTest for the first test case. You should choose names that give the reader an idea what is going on there.

You can build the test application as usual by doing cmt make from your cmt directory.

Running standalone tests

The executable will be put into the build directory and has usually to be called from there with something like this:

../$CMTCONFIG/utestExample.exe -l error

the -l option sets the level of detail of the output produced by the test. Possible options are given here.

Also have a look at utestExample.exe --help for a full list of command line arguments.

For the example above you should get the following output:

Running 1 test case...
../src/utestExample.cxx(18): error in "adderTest": check addtest(3,2) == 4 failed

*** 1 failure detected in test suite "utestExample"

It is good practice to make each test fail on purpose when you run it for the first time. In that way you can check if your test is actually catching the problem you want to have tested. Running a corrected version of the test again gives:

running 1 test case...

*** No errors detected

Refined Checks

BOOST_CHECK is the very basic check. There are couple of refined checkers: BOOST_CHECK_MESSAGE and BOOST_CHECK_EQUAL mainly provide nicer log output while BOOST_CHECK_CLOSE is useful for numerical checks. BOOST_CHECK_THROW can be used to check if an exception of a particular type is thrown. BOOST_CHECK_REQUIRE allows you to abort testing if this test fails. BOOST_IS_DEFINED allows to check preprocessor statements.

Note that most checkers come in three variants corresponding to different severity levels: WARN, REQUIRE, CHECK

A full list is here.

Test suites and fixtures

Integrating Boost.Test and GaudiTest

Running the tests standalone is very quick and convenient. For larger projects and to include them in the nightly it is straight forward to include them into the Gaudi QMTests. A simple qms file looks like the following:

<?xml version="1.0" ?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
<extension kind="test">
  <argument name="program"><text>../../$CMTCONFIG/utestExample.exe</text></argument>
  <argument name="exit_code"><integer>0</integer></argument>
  <argument name="validator"><text>
stderr.find("*** No errors detected");
</text></argument>
</extension>

Here a validator is used to check for the message from Boost.Test that indicates that all unit tests have succeeded. *** No errors detected

You will have to decide yourself how you want to do the organization of tests into Boost.Test suites and QMTest suites.

Test-Driven Development

The basic idea of test-driven development (TDD) is that whenever you set out to program something new, you first write a test, then you implement the solution. Below is a simple schema how that is meant to work. There also is a decent <a target="_blank" href="http://en.wikipedia.org/wiki/Test-driven_development">wikipedia article on TDD</a>.

TDD concept

Edit | Attach | Watch | Print version | History: r1 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r1 - 2013-04-29 - SebastianNeubert
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LHCb All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback