了解 Boost 单元测试框架
作者:网络转载 发布时间:[ 2013/9/3 10:07:46 ] 推荐标签:
清单 11. 由于超过公差限制,比较失败
[arpan@tintin] ./a.out
Running 1 test case...
sq.cpp(18): error in "test": difference between f1{567.010132} and
result * result{567.010193} exceeds 1e-07
*** 1 failure detected in test suite "floatingTest"
生产软件中另一个常见的问题是比较 double 和 float 类型的变量。BOOST_CHECK_CLOSE_FRACTION 的优点是它不允许进行这种比较。这个宏中的左值和右值必须是相同类型的 — 即要么是 float,要么是 double。在 清单 12 中,如果 f1 是 double,而 result 是 float,在比较时会出现错误。
清单 12. 错误:BOOST_CHECK_CLOSE_FRACTION 的左值和右值参数的类型不同
[arpan@tintin] g++ sq.cpp -I/u/c/lib/boost
/u/c/lib/boost/boost/test/test_tools.hpp:
In function
`bool boost::test_tools::tt_detail::check_frwd(Pred,
const boost::unit_test::lazy_ostream&,
boost::test_tools::const_string, size_t,
boost::test_tools::tt_detail::tool_level,
boost::test_tools::tt_detail::check_type,
const Arg0&, const char*,
const Arg1&, const char*, const Arg2&, const char*)
[with Pred = boost::test_tools::check_is_close_t, Arg0 = double,
Arg1 = float, Arg2 = boost::test_tools::fraction_tolerance_t<double>]':
sq.cpp:18: instantiated from here
/u/c/lib/boost/boost/test/test_tools.hpp:523: error: no match for call to
`(boost::test_tools::check_is_close_t) (const double&, const float&,
const boost::test_tools::fraction_tolerance_t<double>&)'
定制的断言支持
Boost 测试工具验证 Boolean 条件。可以通过扩展测试工具支持更复杂的检查 — 例如,判断两个列表的内容是否相同,或者某一条件对于向量的所有元素是否都是有效的。还可以通过扩展 BOOST_CHECK 宏执行定制的断言检查。下面对用户定义的 C 函数生成的列表内容执行定制的检查:检查结果中的所有元素是否都大于 1。定制检查函数需要返回 boost::test_tools::predicate_result 类型。清单 13 给出了详细的代码。
清单 13. 使用 Boost 测试工具验证复杂的断言
#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
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( )
predicate_result 对象有一个隐式的构造函数,它接受一个 Boolean 值,因此即使 validate_list 的期望类型和实际返回类型不同,代码仍然会正常运行。
还有另一种用 Boost 测试复杂断言的方法:BOOST_CHECK_PREDICATE 宏。这个宏的优点是它不使用 predicate_result。但缺点是语法有点儿粗糙。用户需要向 BOOST_CHECK_PREDICATE 宏传递函数名和参数。清单 14 的功能与 清单 13 相同,但是使用的宏不同。注意,validate_result 的返回类型现在是 Boolean。
清单 14. BOOST_CHECK_PREDICATE 宏
#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
bool 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_PREDICATE( validate_list, list1 );
}
BOOST_AUTO_TEST_SUITE_END( )
在一个文件中包含多个测试套件
可以在一个文件中包含多个测试套件。文件中定义的每个测试套件必须有一对 BOOST_AUTO_TEST_SUITE... BOOST_AUTO_TEST_SUITE_END 宏。清单 15 给出了在同一个文件中定义的两个测试套件。在运行回归测试时,用预定义的 –log_level=test_suite 选项运行可执行程序。在 清单 16 中可以看到,使用这个选项生成的输出很详细,有助于进行快速调试。

sales@spasvo.com