I've just started using Boost.Test to get to know unit testing a bit better. I use it to try a Fixed Point number class that I made. For those who wonder what a fixed point number is, in short, it's a float in an integer. This is useful when your hardware doesn't have a FPU, like the Nintendo DS. But this is not my point, I'll discuss that in a proper blog post. This is about a problem I had when I tried to compile my unit test program on Linux.

Installing the Boost library on an Ubuntu system is really easy. It's just a sudo apt-get install libboost-dev or a click on this link (note: this link uses the apt protocole that only works on supporting systems, such as Debian and derivatives). On Windows, I preferred to recompile the library than to download the installer because it required me to fill a form for a company I didn't know and don't care about. This was actually not hard: Boost has it's own build system capable of... building itself! Yes! The builder first builds itself and then builds the library.

Compilation is actually not necessary. At least not for all the modules of Boost. In the case that interest me, Boost.Test can work either with headers only or with a runtime version. I still don't know what's in the runtime that you can't find in the headers, but I'll figure this out another time. Trying the Unit Test Framework was a breeze. Here's an extract:

#include "FixedPointMath.hpp"
 
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
 

BOOST_AUTO_TEST_CASE( Constructors )
{
    FP12 a(12);
    FP12 b(23);
    FP12 c;
    FP12 d( b );
    FP12 e( 3.4f );
    FP12 f = FP12(42) / FP12(6);
    FP12 ff = FP12(45) / FP12(6);

 
    BOOST_CHECK_EQUAL( a.toInt(), 12 );
    BOOST_CHECK_EQUAL( b.toInt(), 23 );
    BOOST_CHECK_EQUAL( c.toInt(), 0 );
    BOOST_CHECK_EQUAL( d.toInt(), 23 );
    BOOST_CHECK_EQUAL( e.toInt(), 3 );
    BOOST_CHECK_EQUAL( f.toInt(), 7 );
    BOOST_CHECK_EQUAL( ff.toInt(), 7 );

}

And this is all you have to do. The macro BOOST_TEST_MAIN takes care of initializing a main entry point for you and BOOST_AUTO_TEST_CASE creates a test case and a default test suite without any work from you. You just specify the name of the test case. Is the case where all the tests are ok, the output looks like this:

Running 1 test case...

*** No errors detected

Introducing an error on purpose gives you this;

Running 1 test case...
UnitTestFixedPoint.cpp(34): error in "Constructors": check ff.toInt() == 8 failed [7 != 8]

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

You can then move on to more complicated tests. Anyway, this piece of code doesn't compile on Linux. You can't just do g++ UnitTestFixedPoint.cpp -o UnitTestFixedPoint because, obviously, you need to link against the Unit Test Framework and you have to tell GCC which library to pick. Automagically, there's nothing to do in Visual Studio and Boost.Test knows how to tell it what the right library is. Fine. Do:

g++ UnitTestFixedPoint.cpp \
   -o UnitTestFixedPoint \
   -lboost_unit_test_framework

>Undefined reference to `main'

Oh come on! Now what? Some research on the internet bring the following result:

For your program to successfully link with the dynamic library the flag BOOST_TEST_DYN_LINK needs to be defined both during dynamic library build and during your program compilation.

Why didn't you say so? Ok, now with some patching for the 'Nux version only, this works much better:

#define BOOST_TEST_MAIN
 
#if !defined( WIN32 )
    #define BOOST_TEST_DYN_LINK
#endif
 
#include <boost/test/unit_test.hpp>

More on that when I'm satisfiyed with my tests!