Skip to content

Boost:Test

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: 예외처리.
  • 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()

이후 LDFLAGS-lboost_unit_test_framework를 추가하고 컴파일 한다.

test/included

included아래의 헤더를 사용하면 main이 포함되어 있어, 별도로 boost_unit_test_framework를 링크할 필요가 없다.

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

하지만 위와 같이 하면 빌드가 더 오래 걸리니 아래와 같이 컴파일 하자.

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

Hoe to use

boost/test/test_tools.hpp를 참조하면 된다.

  • #define BOOST_TEST_DYN_LINK: boost_unit_test_framework를 동적으로 링크하기 위해 Define 해야 한다.
  • #define BOOST_TEST_MODULE test: 테스트 모듈 이름.
  • BOOST_AUTO_TEST_CASE(test_case_name) { /* test body */ }: 자동으로 추가되는 테스트 define.
  • BOOST_AUTO_TEST_SUITE(vtest_basic); ~ BOOST_AUTO_TEST_SUITE_END(): 테스트 스위트 OPEN ~ END. 테스트케이스를 묶을 수 있다. 또한 if문과 같이 중첩도 가능하다.
  • BOOST_CHECK(true);: Assert와 동일.
  • BOOST_CHECK_EQUAL(1, 1);: 두 인자의 동등함을 비교한다.
  • BOOST_TEST_CHECKPOINT("before divzero"); i=100/0;: 시그널이나 트랩등이 걸린 경우 마지막 체크 포인트를 찍어준다.
  • BOOST_TEST_MESSAGE("message");: 상세 메시지를 출력한다. 단 일반적으로 출력되지 않고 명령행 인자로 --log_level=all를 넘겨야 한다. 또는 환경변수에 BOOST_TEST_LOG_LEVEL=all를 설정해도 된다. (boost.test의 parameters 참조)

class test

클래스를 사용한 좀 복잡한 테스트 스위트는 아래와 같다.

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()

참고로 아래와 같은 방식으로도 가능하다.

#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

MinGW에서 아래와 같은 에러 메시지가 출력될 수 있다.

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() ) );

이 경우 #include 앞에 아래와 같이 추가하면 된다.

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

multiple cpp files

여러 개의 소스파일에 유닛 테스트를 분리하고 싶을 경우 아래와 같이 하면 된다.

우선 첫 번째 소스 파일에 모듈명을 추가하여 테스트 케이스를 추가한다.

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

그리고 두 번째 이후의 소스 파일은 모듈을을 추가하지 말고 오직 헤더만 추가한다.

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

Favorite site