1) 准备
1.1) 编译boost test
cd boost_1_55_0
# On Windows
bootstrap.bat
b2 --toolset=msvc-10.0 --build-type=minimal --with-test runtime-link=static stage
# 1) --toolset=msvc-10.0: 指定编译器,这儿是VS2010。其他版本可见链接1。
# 2) --build-type=minimal: 默认,按其描述相当于设定了下述属性:
# link=static runtime-link=shared threading=multi variant=debug,release
# 3) --with-test: 指定编译test。一旦用了'--with',就只编译指定库了。
# 4) runtime-link=static: 添加静态链接运行时库。link与runtime-link区分,可见链接2。
# 5) stage: 只编译和安装库文件,也就是不会包含头文件。
# On Linux
# 是否已预安装
ll /usr/lib/libboost*
# yum list installed boost*
./bootstrap.sh
./b2 --toolset=gcc --build-type=minimal --with-test stage
# 1) --prefix: 安装路径,默认/usr/local。
# 2) --build-type=minimal: 默认,Linux下相当于设定了下述属性:
# link=static,shared threading=multi variant=release
# 帮助
./b2 --help
./b2 --show-libraries
参考
- b2 Invocation
- Getting Started on Windows
- Getting Started on Unix Variants
中文的话,可参考这两篇:
- Boost下载安装编译配置使用指南
- VS2010 编译安装boost库
链接
- C++ Compilers: Microsoft Visual C++
- link和runtime-link,搭配shared和static
1.2) 引入boost test
# On Windows,静态链接方式
"IncludePath" += boost_1_55_0
"LibraryPath" += boost_1_55_0\stage\lib
指定选项:/EHa,/MT[d]
# On Linux,动态链接方式
定义宏:BOOST_TEST_DYN_LINK
链接时:-lboost_unit_test_framework
2) 使用
官方文档Boost Test Library讲的很详细。主要是几下几方面:
test_hello.cc
#define BOOST_TEST_MODULE MyTest
#include <boost/test/unit_test.hpp>
int add( int i, int j ) { return i+j; }
BOOST_AUTO_TEST_CASE( my_test )
{
// seven ways to detect and report the same error:
BOOST_CHECK( add( 2,2 ) == 4 ); // #1 continues on error
BOOST_REQUIRE( add( 2,2 ) == 4 ); // #2 throws on error
if( add( 2,2 ) != 4 )
BOOST_ERROR( "Ouch..." ); // #3 continues on error
if( add( 2,2 ) != 4 )
BOOST_FAIL( "Ouch..." ); // #4 throws on error
if( add( 2,2 ) != 4 ) throw "Ouch..."; // #5 throws on error
BOOST_CHECK_MESSAGE( add( 2,2 ) == 4, // #6 continues on error
"add(..) result: " << add( 2,2 ) );
BOOST_CHECK_EQUAL( add( 2,2 ), 4 ); // #7 continues on error
}
官方的例子,很简单:
- “BOOST_TEST_MODULE”,定义测试模块。之后再include “unit_test.hpp”。
- “BOOST_AUTO_TEST_CASE”,自动注册测试用例。
- 测试工具分为"WARN”,“CHECK"和"REQUIRE"三个等级。“CHECK"与"REQUIRE"差别为:前者即使失败,也仍然继续;后者则认为是必须的,为严重错误,直接退出当前测试。
测试工具参考,见testing tools reference。
用以下宏把"TEST_CASE"包起来即成:
BOOST_AUTO_TEST_SUITE(test_suite_name)
BOOST_AUTO_TEST_SUITE_END()
test_suite.cc
#define BOOST_TEST_MODULE MySuiteTest
#include <boost/test/included/unit_test.hpp>
/* test_suite1 start */
BOOST_AUTO_TEST_SUITE( test_suite1 )
// test_case1 in test_suite1
BOOST_AUTO_TEST_CASE( test_case1 )
{
BOOST_WARN( sizeof(int) < 4 );
}
// test_case2 in test_suite1
BOOST_AUTO_TEST_CASE( test_case2 )
{
BOOST_REQUIRE_EQUAL( 1, 2 ); // note: REQUIRE
BOOST_FAIL( "Should never reach this line" );
}
BOOST_AUTO_TEST_SUITE_END()
/* test_suite1 end */
/* test_suite2 start */
BOOST_AUTO_TEST_SUITE( test_suite2 )
// test_case3 in test_suite2
BOOST_AUTO_TEST_CASE( test_case3 )
{
BOOST_CHECK( true );
}
BOOST_AUTO_TEST_SUITE_END()
/* test_suite2 end */
// test_case_on_file_scope
BOOST_AUTO_TEST_CASE( test_case_on_file_scope )
{
BOOST_CHECK( true );
}
/* test_suite2 start */
BOOST_AUTO_TEST_SUITE( test_suite2 )
// test_case4 in test_suite2
BOOST_AUTO_TEST_CASE( test_case4 )
{
BOOST_CHECK( false );
}
BOOST_AUTO_TEST_SUITE_END()
/* test_suite2 end */
- 上述定义了两个"TEST_SUITE”:test_case1、test_case1在test_suite1内;test_case3、test_case4在test_suite2内。
- 注意test_case_on_file_scope,其上下分别是test_suite2的test_case3、test_case4。也就是测试套件可以分为多个部分,以便放在不同文件。
重复的测试数据,都可以放到一个夹具里。其模板如下:
struct <fixture-name>{
<fixture-name>(); // setup function
~<fixture-name>(); // teardown function
};
然后,使用时:
- “BOOST_FIXTURE_TEST_CASE”,用在测试用例上。
- “BOOST_FIXTURE_TEST_SUITE”,用在测试套件上。这样的话,测试套件每个测试用例就不用写了。
- “BOOST_GLOBAL_FIXTURE”,用在全局上。
test_suite.cc
#define BOOST_TEST_MODULE MyFixtureTest
#include <boost/test/included/unit_test.hpp>
#include <iostream>
/* 3) Global fixture */
struct MyConfig {
MyConfig() : g_i( 0 )
{
instance() = this;
std::cout << "global setup\n";
}
~MyConfig()
{
std::cout << "g_i: " << g_i << std::endl;
std::cout << "global teardown\n";
}
static MyConfig *&instance();
int g_i;
};
BOOST_GLOBAL_FIXTURE(MyConfig);
MyConfig *&MyConfig::instance()
{
static MyConfig *s_inst = 0;
return s_inst;
}
/* 1) Per test case fixture */
struct F {
F() : i( 0 ) { std::cout << "setup fixture\n"; }
~F() { std::cout << "teardown fixture\n"; }
int i;
};
BOOST_FIXTURE_TEST_CASE( test_case1, F )
{
BOOST_CHECK( i == 1 ); // failed: i == 0
++i;
}
BOOST_FIXTURE_TEST_CASE( test_case2, F )
{
BOOST_CHECK_EQUAL( i, 0 ); // pass: i == 0
++(MyConfig::instance()->g_i);
}
BOOST_AUTO_TEST_CASE( test_case3 )
{
BOOST_CHECK( true );
std::cout << "g_i: " << MyConfig::instance()->g_i << std::endl;
}
/* 2) Test suite level fixture */
BOOST_FIXTURE_TEST_SUITE( test_suite1, F )
BOOST_AUTO_TEST_CASE( test_case1 )
{
BOOST_CHECK( i == 1 ); // failed: i == 0
++i;
}
BOOST_AUTO_TEST_CASE( test_case2 )
{
BOOST_CHECK_EQUAL( i, 0 ); // pass: i == 0
++(MyConfig::instance()->g_i);
}
BOOST_AUTO_TEST_SUITE_END()
- 输出会有四组"setup fixture"与"teardown fixture”,每个用到的测试用例下各自一份。
- “global setup"与"global teardown"则分别于头尾,只有一个实例。官方文档没看到如何访问其成员,这里用了单例方式来处理。
3) 总结
本文主要介绍了boost单元测试框架的使用。
附1:样例工程btest_start
下载:btest_start.zip。
目录树如下:
btest_start/
├─build/
│ ├─btest_start-gcc.cbp # for gnu gcc
│ └─btest_start-msvc.cbp # for msvc 2010
├─src/
├─third_party/
│ └─boost_1_55_0/
└─tools/
C::B工程,boost_1_55_0/目录Windows上配置时用到了。