清单 15. 使用一个文件中的多个测试套件

#define BOOST_TEST_MODULE Regression
#include <boost/test/included/unit_test.hpp>
typedef struct {
int c;
char d;
double e;
bool f;
} Node;
typedef union  {
int c;
char d;
double e;
bool f;
} Node2;
BOOST_AUTO_TEST_SUITE(Structure)
BOOST_AUTO_TEST_CASE(Test1)
{
Node n;
BOOST_CHECK(sizeof(n) < 12);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(Union)
BOOST_AUTO_TEST_CASE(Test1)
{
Node2 n;
BOOST_CHECK(sizeof(n) == sizeof(double));
}
BOOST_AUTO_TEST_SUITE_END()

  下面是 清单 15 中代码的输出:

  清单 16. 用 –log_level 选项运行多个测试套件

[arpan@tintin] ./a.out --log_level=test_suite
Running 2 test cases...
Entering test suite "Regression"
Entering test suite "Structure"
Entering test case "Test1"
m2.cpp(23): error in "Test1": check sizeof(n) < 12 failed
Leaving test case "Test1"
Leaving test suite "Structure"
Entering test suite "Union"
Entering test case "Test1"
Leaving test case "Test1"
Leaving test suite "Union"
Leaving test suite "Regression"
*** 1 failure detected in test suite "Regression"

  理解测试套件的组织

  到目前为止,本文已经讨论了 Boost 测试实用程序和没有层次结构的测试套件。现在,我们使用 Boost 创建一个测试套件,以外部工具用户常见的方式测试软件产品。在测试框架中,通常有多个套件,每个套件检查产品的某些特性。例如,文字处理程序的回归测试框架应该包含检查字体支持、不同的文件格式等方面的套件。每个测试套件包含多个单元测试。清单 17 提供了一个测试框架示例。注意,代码入口点必须是名为 init_unit_test_suite 的例程。

  清单 17. 创建用于运行回归测试的主测试套件

#define BOOST_TEST_MODULE MasterTestSuite
#include <boost/test/included/unit_test.hpp>
using boost::unit_test;
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;
}

  每个测试套件(比如 清单 17 中的 ts1)都是使用 BOOST_TEST_SUITE 宏创建的。这个宏需要一个字符串作为测试套件的名称。终使用 add 方法,把所有测试套件添加到主测试套件中。同样,我们使用 BOOST_TEST_CASE 宏创建每个测试,然后再使用 add 方法把它们添加到测试套件中。也可以把单元测试添加到主测试套件中,但是不建议这么做。master_test_suite 方法属于 boost::unit_test::framework 名称空间的一部分:它在内部实现一个单实例对象。清单 18 中的代码取自 Boost 源代码本身,解释了这个方法的工作方式。

  清单 18. 理解 master_test_suite 方法

master_test_suite_t&
master_test_suite()
{
if( !s_frk_impl().m_master_test_suite )
s_frk_impl().m_master_test_suite = new master_test_suite_t;
return *s_frk_impl().m_master_test_suite;
}