#include <boost/test/included/unit_test.hpp> 与 #include <boost/test/unit_test.hpp> 区别:
前者直接包含源代码,后者还需链接unit_test的lib
(但前者这样会很容易造成与现有其他代码的种种冲突,像winsock2啊...)
不过boost test 在vs下会通过代码里写像 #pragma comment(lib, "libboost_unit_test_framework-vc90-mt-sgd-1_54.lib")的方式来自动链接库,
(关于boost库的命名约定,可自行上网搜索,注意静态链接和动态链接的区别,此处为静态链接)
如果怕有很多不清楚的问题,想自己动手链接,需定义以下这个宏即可:
#define BOOST_ALL_NO_LIB
关于程序的入口,boost test里是有已经定义了的main函数的,在 boost_1_54_0\boost\test\impl\unit_test_main.ipp中,
int BOOST_TEST_CALL_DECL main( int argc, char* argv[] ) { // prototype for user's unit test init function #ifdef BOOST_TEST_ALTERNATIVE_INIT_API extern bool init_unit_test(); boost::unit_test::init_unit_test_func init_func = &init_unit_test; #else extern ::boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ); boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite; #endif return ::boost::unit_test::unit_test_main( init_func, argc, argv ); }
若想自己定义main函数,再在其中模仿boost的main编写调 用::boost::unit_test::unit_test_main( init_func, argc, argv )也是可以的(假如再有TCHAR**和char**的问题,强转一下,用时再转一下回来应该就可以的),只用定义一下宏:
#define BOOST_TEST_NO_MAIN
但我试了下,没有用,会提示链接重定义main的错误。以下是我的理解,不知道对不对:
这些宏定义是编译器预处理时的事,这时有这个宏定义才能跳过boost的main,也就是boost的main已经编到boost的lib中了,所以就会重定义了。
可见,宏这些在链接期根本不管作用了。
如开头无 #define BOOST_TEST_MODULE xxxx,则需 定义入口:
test_suite* __cdecl init_unit_test_suite(int, char* [ ])
{
return 0;
}
测试工具的三个主要类别是 BOOST_WARN、BOOST_CHECK 和 BOOST_REQUIRE
BOOST_CHECK 和 BOOST_REQUIRE 之间的差异在于:对于前者,即使断言失败,测试仍然继续执行;而对于后者,认为这是严重的错误,测试会停止
【1】BOOST_CHECK(predicate):断言测试通过,如不通过不影响程序执行
【2】BOOST_REQUIRE(predicate):要求测试必须通过,否则程序停止执行;
【3】BOOST_ERROR(message):给出一个错误信息,程序继续执行;
【4】BOOST_FAIL(message):给出一个错误信息,程序终止。
float test:
Boost 测试实用程序提供了 BOOST_WARN_CLOSE_FRACTION、BOOST_CHECK_CLOSE_FRACTION 和 BOOST_REQUIRE_CLOSE_FRACTION 宏。
要想使用这三个宏,必须 #include <boost/test/floating_point_comparison.hpp>。
用法: BOOST_CHECK_CLOSE_FRACTION (left-value, right-value, tolerance-limit);
i.e.: BOOST_CHECK_CLOSE_FRACTION (f1, result * result, 0.0001);// 指定公差限制为 0.0001
(生产软件中另一个常见的问题是比较 double 和 float 类型的变量。BOOST_CHECK_CLOSE_FRACTION 的优点是它不允许进行这种比较。
这个宏中的左值和右值必须是相同类型的 ― 即要么是 float,要么是 double。)
验证 Boolean 条件 & 定制的断言支持:
①定制检查函数需要返回 boost::test_tools::predicate_result 类型。
i.e.:
// assert all element > 1
boost::test_tools::predicate_result validate_list(std::list<int>& L1)
{
std::list<int>::iterator it1 = L1.begin( );
for (; it1 != L1.end( ); ++it1)
{
if (*it1 <= 1) return false;
}
return true;
}
BOOST_AUTO_TEST_SUITE ( test )
BOOST_AUTO_TEST_CASE( test )
{
std::list<int>& list1 = user_defined_func( );
BOOST_CHECK( validate_list(list1) );
}
BOOST_AUTO_TEST_SUITE_END( )
②或 用BOOST_CHECK_PREDICATE 宏 替代。
i.e.:
bool validate_list(std::list<int>& L1);// note return type is bool
...
std::list<int>& list1 = user_defined_func( );
BOOST_CHECK_PREDICATE( validate_list, list1 );//需要 传递 函数名 和 参数
...
可以在一个文件中包含多个测试套件。文件中定义的每个测试套件必须有一对 BOOST_AUTO_TEST_SUITE... BOOST_AUTO_TEST_SUITE_END 宏。
i.e.:
BOOST_AUTO_TEST_SUITE(Structure)
BOOST_AUTO_TEST_CASE(Test1) { }
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(Union)
BOOST_AUTO_TEST_CASE(Test1) { }
BOOST_AUTO_TEST_SUITE_END()
参考 理解测试套件的组织(清单17):
// 手工组织?:
test_suite* init_unit_test_suite( int argc, char* argv[] )
{
test_suite* ts1 = BOOST_TEST_SUITE( "test_suite1" );
ts1->add( BOOST_TEST_CASE( &test_case1 ) );
ts1->add( BOOST_TEST_CASE( &test_case2 ) );
test_suite* ts2 = BOOST_TEST_SUITE( "test_suite2" );
ts2->add( BOOST_TEST_CASE( &test_case3 ) );
ts2->add( BOOST_TEST_CASE( &test_case4 ) );
framework::master_test_suite().add( ts1 );
framework::master_test_suite().add( ts2 );
return 0;
}
装备 (是指在执行测试之前设置一个环境,在测试完成时清除它。清单19):
struct F{
F() : i(0){}
int i;
};
BOOST_FIXTURE_TEST_CASE( test_case1, F )
{
BOOST_CHECK( i == 1 );
++i;
}
宏定义:
#define BOOST_FIXTURE_TEST_CASE( test_name, F ) \
struct test_name : public F { void test_method(); }; \
...
(only struct, as private val in base can't be accessed by derive)