Skip to content
Search

Boost:Test

lastmod 2015-04-09created 2015-03-1716 edits

Test Tools

The UTF's supplies a toolbox of testing tools to ease creation and maintenance of test programs and provide a uniform error reporting mechanism. The toolbox supplied in most part in a form of macro and function declarations. While the functions can be called directly, the usual way to use testing tools is via convenience macros. All macros arguments are calculated once, so it's safe to pass complex expressions in their place. All tools automatically supply an error location: a file name and a line number. The testing tools are intended for unit test code rather than library or production code, where throwing exceptions, using assert(), boost::concept_check or BOOST_STATIC_ASSERT() may be more suitable ways to detect and report errors. For list of all supplied testing tools and usage examples see the reference.

Testing tools flavors

All the tools are supplied in three flavors(levels): WARN, CHECK and REQUIRE. For example: BOOST_WARN_EQUAL, BOOST_CHECK_EQUAL, BOOST_REQUIRE_EQUAL. If an assertion designated by the tool passes, confirmation message can be printed in log output. If an assertion designated by the tool failed, depending on the level following will happened:

Level

Test log content

Errors counter

Test execution

WARN

warning in <test case name>: condition <assertion description> is not satisfied

not affected

continues

CHECK

error in <test case name>: test <assertion description> failed

increased

continues

REQUIRE

fatal error in <test case name>: critical test <assertion description> failed

increased

aborts

Reference

  • BOOST_CHECK_THROW: Exception handling.
  • BOOST_<level>
  • BOOST_<level>_BITWISE_EQUAL
  • BOOST_<level>_CLOSE
  • BOOST_<level>_CLOSE_FRACTION
  • BOOST_<level>_EQUAL
  • BOOST_<level>_EQUAL_COLLECTION
  • BOOST_<level>_EXCEPTION
  • BOOST_<level>_GE
  • BOOST_<level>_GT
  • BOOST_<level>_LE
  • BOOST_<level>_LT
  • BOOST_<level>_MESSAGE
  • BOOST_<level>_NE
  • BOOST_<level>_NO_THROW
  • BOOST_<level>_PREDICATE
  • BOOST_<level>_SMALL
  • BOOST_<level>_THROW
  • BOOST_ERROR
  • BOOST_FAIL
  • BOOST_IS_DEFINED

Sample test code

#ifdef __MINGW32__
// Mingw doesn't define putenv() needed by Boost.Test
extern int putenv(char*);
#endif

#define BOOST_TEST_MODULE enumtest
#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(enumtest) 

BOOST_AUTO_TEST_CASE(test1)
{
    BOOST_CHECK(false);
}

BOOST_AUTO_TEST_SUITE_END()

Then add -lboost_unit_test_framework to LDFLAGS and compile.

test/included

The headers under included contain main, so there is no need to link boost_unit_test_framework separately.

#include <boost/test/included/unit_test.hpp>

However, doing it this way makes the build take longer, so compile as follows instead.

#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

Hoe to use

Refer to boost/test/test_tools.hpp.

  • #define BOOST_TEST_DYN_LINK: Must be defined to link boost_unit_test_framework dynamically.
  • #define BOOST_TEST_MODULE test: Test module name.
  • BOOST_AUTO_TEST_CASE(test_case_name) { /* test body */ }: Defines a test that is registered automatically.
  • BOOST_AUTO_TEST_SUITE(vtest_basic); ~ BOOST_AUTO_TEST_SUITE_END(): Test suite OPEN ~ END. Groups test cases together. Suites can also be nested, like if statements.
  • BOOST_CHECK(true);: Same as Assert.
  • BOOST_CHECK_EQUAL(1, 1);: Compares the two arguments for equality.
  • BOOST_TEST_CHECKPOINT("before divzero"); i=100/0;: Marks the last checkpoint when a signal or trap occurs.
  • BOOST_TEST_MESSAGE("message");: Prints a detailed message. However, it is not printed by default; you must pass --log_level=all as a command-line argument. Alternatively, you can set BOOST_TEST_LOG_LEVEL=all as an environment variable. (See the parameters of boost.test)

class test

A somewhat more complex test suite using a class is as follows.

BOOST_AUTO_TEST_SUITE(suite2)
struct adder {
    adder()  { BOOST_TEST_MESSAGE("setup fixture"); }
    ~adder() { BOOST_TEST_MESSAGE("teardown fixture"); }
    int add(int x, int y) { return x+y; }
};

BOOST_FIXTURE_TEST_CASE(test_adder_1, adder)
{
    // adder 의 non-private 멤버에 바로 접근이 가능
    BOOST_CHECK_EQUAL(add(1,1),1);
}

BOOST_AUTO_TEST_SUITE_END()

For reference, the following approach also works.

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Fixtures
#include <boost/test/unit_test.hpp>

struct Massive
{
    int m;

    Massive() : m(2)
    {
        BOOST_TEST_MESSAGE("setup mass");
    }

    ~Massive()
    {
        BOOST_TEST_MESSAGE("teardown mass");
    }
};

BOOST_FIXTURE_TEST_SUITE(Physics, Massive)

BOOST_AUTO_TEST_CASE(specialTheory)
{
    int e = 32;
    int c = 4;

    BOOST_CHECK(e == m * c * c);
}

BOOST_AUTO_TEST_CASE(newton2)
{
    int f = 10;
    int a = 5;

    BOOST_CHECK(f == m * a);
}

Exception test

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

class my_exception{};

BOOST_AUTO_TEST_CASE( test )
{
    int i =  0;
    BOOST_CHECK_THROW( i++, my_exception );
}

Troubleshooting

error: putenv not declared

On MinGW, the following error message may be printed.

C:/boost/boost_1_55_0/boost/test/utils/runtime/config.hpp:95:51: error: 'putenv'
 was not declared in this scope
 putenv( const_cast<char*>( fs.str().c_str() ) );

In this case, add the following before #include.

#ifdef __MINGW32__
// Mingw doesn't define putenv() needed by Boost.Test
extern int putenv(char*);
#endif

multiple cpp files

To split unit tests across multiple source files, do the following.

First, add the module name in the first source file and add test cases.

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE vtest_unit_test
#include <boost/test/unit_test.hpp>
// TODO: Insert test case.

Then, in the second and later source files, do not add the module; include only the header.

#include <boost/test/unit_test.hpp>
// TODO: Insert test case.

Favorite site