C++ Unit Tests With Boost.Test, Part 1

In this post, I will describe how to start making unit tests in C++ with Boost.Test.

The Boost libraries are a large collection of source libraries for C++ programmers. There are many useful libraries in Boost. One of those libraries is Boost.Test, a library for writing and organizing test programs.

Most xUnit test frameworks exploit some form of reflection in a programming language to dynamically execute test code within a test framework. C++ does not have support for reflection and requires that the user register their test code with the test framework. Boost.Test hides the test framework and the registration mechanism behind a series of macros, resulting in a header only library for unit testing.

Unit tests are an important part of modern programming discipline. They are the underpinning of a development style called test-driven development, where you first write a failing test and then write production code to satisfy the test. In this style of development production code is only written in response to a failing test. In turn, the tests are written in response to requirements for changing existing functionality or creating new functionality.

The interesting thing about this sort of development style is that because you’ve written the code in response to a test, you automatically have production code that is designed to be testable. This development style also tends to produce smaller objects that adhere to the single responsibility principle, in other words an object that does one thing only. Smaller objects are easier to test. Smaller objects are more likely to find situations where they can be reused. Of course, you also end up with an ever-increasing regression suite that you can run over your objects to make sure that a change in one place didn’t break something in code you’ve already written.

Because most xUnit test frameworks are inspired by JUnit, the defacto test framework for Java, they rely on reflection to get the job done. Without reflection, C++ lagged in having a defacto test framework that supported a wide variety of testing scenarios. With the Boost.Test library, we can write unit tests in C++ with a minimal amount of fussing around with the registration mechanisms.

In order to use Boost.Test, you will need to install it and configure Visual Studio’s C++ project directories to look for Boost’s files. I recommend that you use the prepackaged MSI installer for Boost that will allow you to select which precompiled libraries you might like to use (debug, release, multi-threaded, etc.). To use Boost.Test you will only need header libraries, so you can download the zip distribution and unpack it to a suitable folder if you wish to avoid the large download of precompiled libraries. (Some libraries in Boost require are not header-only libraries and require building.) Either way, you can find what you need from the boost download page. This article was created with the 1.35 release, but should work with any subsequent release of boost. Finally, configure the C++ include directories to include the directory where you installed boost. This should be the directory containing the folders “boost”, “doc”, “lib”, etc.

So how do we organize unit tests with Boost.Test? First, all the tests are organized together into a single executable program that executes all the registered test cases one by one. Boost provides a standard implementation of main that executes all the registered test cases and macros to create a test case and register it with the framework. In Visual Studio, simply follow these steps:

  1. Create a new Win32 Console Project called “Test”.
  2. Accept the default settings in the Win32 Application Wizard.
  3. Replace the contents of Test.cpp with the following source code:
    #define BOOST_TEST_MAIN
    #include <boost/test/unit_test.hpp>
    
  4. Change the project options for Test.cpp to not use precompiled headers. Remember to change the options for both Debug and Release configurations.
  5. Compile and link the project.
  6. Run the project to see the following output:
    Test setup error: test tree is empty
    

    The return value of the executable will be non-zero since an error was encountered during test execution.

  7. Add the following line to stdafx.h:
    #include <boost/test/unit_test.hpp>
    

    This will include the Boost.Test library in all source files.

Now we are ready to write our first test case. Create a new cpp source file called Test1.cpp in the Test project and add the following code to the file:

#include "stdafx.h"

BOOST_AUTO_TEST_CASE(Test1)
{
    BOOST_REQUIRE(true);
}

Compile and link the project and run the test executable again to get the following output:

Running 1 test case...

*** No errors detected

So now we have created a test executable and a simple unit test that doesn’t do much more than exercise the test framework. What we’d also like is for our build to run the unit tests every time we compile and fail the build when the unit tests fail. We can take care of that by configuring our unit tests to run as a Post-Build event on the unit test project:

  1. Open the project properties dialog for the Test project.
  2. Select “All Configurations” from the Configuration combobox in the upper left.
  3. Expand the Configuration Properties / Build Events category in the tree view on the left and select Post-Build Event.
  4. For the value of the Command Line property enter the value “$(TargetPath)”.
  5. For the value of the Description property enter the value “Running unit tests…”.
  6. Click OK.

To check that we’ve configured everything properly, change “BOOST_REQUIRE(true);” to “BOOST_REQUIRE(false);” to force the unit test to fail. Now build the solution and the build should fail with output similar to the following in the Output pane in Visual Studio:

1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1>Compiling...
1>Test1.cpp
1>Linking...
1>Embedding manifest...
1>Running unit tests...
1>Running 1 test case...
1>c:/tmp/code/boost.test/test/test1.cpp(5): fatal error in "Test1": critical check false failed
1>*** 1 failure detected in test suite "Master Test Suite"
1>Project : error PRJ0019: A tool returned an error code from "Running unit tests..."
1>Build log was saved at "file://c:\tmp\Code\Boost.Test\Test\Debug\BuildLog.htm"
1>Test - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The Visual Studio errors window will contain an entry for the failed assertion that you can double-click to take you to the location in the test code that failed.

This covers the basics of using Boost.Test for unit testing in C++ under Visual Studio. Part 2 will cover more of the macros provided by Boost.Test for making assertions and organizing your tests.

[Updated to favor BOOST_REQUIRE over BOOST_CHECK.]

17 Responses to “C++ Unit Tests With Boost.Test, Part 1”

  1. theOcelot Says:

    I like it!

    PS: It should be mentioned that there is a non-header-only version of Boost.Test, which cuts down on compile time.

    Like

    • legalize Says:

      Looking more closely at Boost 1.53, it seems that I wrote “header-only” in the above but I am referring to the library-based header, <boost/test/unit_test.hpp>. The header-only version of the library is <boost/test/included/unit_test.hpp>. I will update this tutorial and the other parts to reflect this.

      Like

  2. legalize Says:

    That’s a good point. I’ve used the header-only version with the headers included in the precompiled header and has been OK so far. When you accumulate thousands of tests, it might be faster to switch to the library version. To start off I like header-only libraries because it simplifies the use of boost.

    Like

  3. C++ Unit Tests With Boost.Test, Part 2 « Legalize Adulthood! Says:

    […] Unit Tests With Boost.Test, Part 2 5-July-2009 — legalize In Part 1 of this series, I discussed how to setup a basic C++ unit test project that executed the unit tests […]

    Like

  4. Description Helpers For Direct3D 10, 10.1 and 11 « Legalize Adulthood! Says:

    […] with the builders are suites of C++ unit tests written with Boost.Test for testing all the functionality of the builders. You will need a boost distribution if you want […]

    Like

  5. kr1zz Says:

    Thank you very much, this introduction to boost.test is very gentle and quick :-)

    Like

  6. Agnel C J Kurian Says:

    From here: http://www.boost.org/doc/libs/1_35_0/more/getting_started/windows.html#pch

    “There’s no problem using Boost with precompiled headers; these instructions merely avoid precompiled headers because it would require Visual Studio-specific changes to the source code used in the examples.”

    The above refers to boost in general and not specifically to boost::test. So is it alright to use PCH with boost::test?

    Like

    • legalize Says:

      I haven’t had any problems using precompiled headers with Boost.Test.

      If you read through the steps in Part 1, you’ll see I give instructions for how to create the initial test project using precompiled headers.

      Like

  7. Unit Testing in C++ - C++ and more! Says:

    […] A five part series on C++ unit tests with Boost.Test. […]

    Like

  8. Tdd with visual studio and boost.test | Brain Dump Says:

    […] with visual studio and boost.test Posted on 2012/02/05 by mschinz http://legalizeadulthood.wordpress.com/2009/07/04/c-unit-tests-with-boost-test-part-1/ This entry was posted in Uncategorized by mschinz. Bookmark the […]

    Like

  9. adamthecoder Says:

    This is the best boost test tutorial out here, thank you for taking the time make it.

    Like

  10. savitha Says:

    Hi Legalize,

    Can you please help with a problem I am facing. I started with the first steps (as described in your part 1 article) to use the unit test framework.

    I just have the following:
    #include

    #define BOOST_TEST_MAIN
    I am seeing the following link error:

    Cannot open file:
    libboost_unit_test_framework-vc100-mt-gd-1_53.lib
    This file is not to be found in the boost folders.
    What could be going on?

    Like

    • legalize Says:

      Hi Savitha,

      It sounds like you either don’t have the boost library directory in your linker search path, or you don’t have the built libraries.

      To build the libraries, open a Visual Studio 2012 Command Prompt window and cd to your boost distribution and follow the build instructions.

      Like

      • savitha Says:

        I have the boost library directory in my linker search path. But the .lib file it tried to open is not present anywhere under the boost distribution. So, do I have to build the libraries then? Would this be step 4.2 in the build instructions? Or would it be step 5.2? I tried the ‘bootstrap’ command and it is not recognized. I tried this from the root directory for boost distribution.

        Like

  11. savitha Says:

    Hi, if I try with the include boost/test/included/unit_test.hpp, it goes through.
    I then added the next two lines in a Test1.cpp file:
    BOOST_AUTO_TEST_CASE(Test1)
    {
    BOOST_REQUIRE(true);
    }
    It doesnt link, gives me several errors in link

    Like

  12. 000000000 Says:

    good information

    Like

  13. Two Sessions Accepted for C++ Now! 2014 (May 12-17, 2014) | Legalize Adulthood! Says:

    […] work through the tutorials I wrote in 2009 on practicing test-driven development using Boost.Test: Part 1, Part 2, Part 3, Part 4 and Part 5. You can also work through the Tutorials in my Boost.Test […]

    Like


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: