不倦的候鸟成长日记

——候鸟,候补的菜鸟也
随笔 - 6, 文章 - 0, 评论 - 5, 引用 - 0
数据加载中……

[转]Boost Test Library

boost 的 Test

test 库中有如下的组件:
Execution Monitor  一个基本用于 program 和 test program 的异常与错误检测与报告机制,Execution Monitor 调用用户提供的函数并报告所有捕获的运行时的异常,它只被其他 Boost Test Library components 内部调用,当然也可以用于一些 production environment 控制那些会导致程序崩溃的函数的调用;

Program Execution Monitor  一个简单的 helper facility 用于监控一个程序的运行,Program Execution Monitor 提供了 main() 函数和 Execution Monitor 监控程序的执行,可以用以 production environment 产生一致错误报告,控制在 test environment 环境中运行的程序,直接使用 Test Execution Monitor;

Test Tools  一个用以进行 testing 的一个 toolbox,Test Tools 被用来测试在 Test Execution Monitor 或 Unit Test Framework 控制下运行的程序;

Test Execution Monitor  让一个测试程序在 monitored environment 环境中运行,Test Execution Monitor 提供了 main() 来控制被测试程序的运行并可以让 Test Tools 实现测试的逻辑,它被用在 test environment,如果要控制 production code 的运行使用 Program Execution Monitor;

Unit Test Framework  用以简化编写和组织 test cases 的 framework,支持简单函数或者是成员函数编写的 test cases 并将他们组织成一个 test suites 的 tree,该 framework 使用 Test Tools 来实现 test cases 并提供了一种机制用以管理 log report level 和 result report level;

minimal testing facility  提供 Boost Test 最初版本的提供的功能的简单 facility,提供了和 Test Execution Monitor 一样的机制,但额外定义了一些简单提供 Test Tools 类似功能的 test tools,它不需要和任何的外部组件 link,适合简单和快速测试的需要,使用于 test environment。
(http://yaekees.spaces.live.com/blog/cns!1955EE8C6707277A!146.entry)


boost Test 的 Execution Monitor

使用 Execution Monitor 的三部曲:
1. #include <boost/test/execution_monitor.hpp>
2. Make an instance of boost::execution_monitor
3. Optionally register custom exception translators for exception classes you want special processing
 
调用 execution_monitor::execute( function_to_monitor, catch_system_exception, timeout ) 运行 monitored function。如果调用成功则返回一个 integer value,如果有如下的事情发生
1. Uncaught C++ exception
2. hardware or software signal, trap, or other exception
3. Timeout reached
4. debug assert event occurred (under Microsoft Visual C++ or compatible compiler)
the method execution_monitor::execute( ... ) throws the boost::execution_exception
如果希望程序 error message 被转化为  execution_exception 的 error message,则扔出如下的三类异常:C string,std:string,any exception class in std::exception hierarchy。
 
终止 monitored function 而不让 Execution Monitor 报告 any error 的最佳方法是抛出 boost::execution_aborted。如果不喜欢 "unknown exception caught" message 而更愿意使用自定义的 exception,可以向 execution monitor 为 any exception types 注册 translator 函数,如
ex_mon.register_exception_translator<my_exception1>( &translate_my_exception1 );
my_exception1 是异常类型,translate_my_exception1 是异常处理函数。
class execution_monitor {
public:
    virtual     ~execution_monitor();
   
    template<typename Exception, typename ExceptionTranslator>
    void        register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* = 0 );
 
    int         execute( unit_test::callback0<int> const& F, bool catch_system_errors = true, int timeout = 0 );
}; // exception monitor
 
Execution Monitor 用 boost::execution_exception 报告捕获的问题,其最大的特点是不分配任何 memory 因此在内存稀缺环境中使用。
class execution_exception {
public:
    execution_exception( error_code ec, const_string what_msg );
    enum error_code {
        cpp_exception_error,    // see note (1) below
        user_error,             // user reported nonfatal error
        system_error,           // see note (2) below
        timeout_error,          // only detectable on certain platforms
        user_fatal_error,       // user reported fatal error
        system_fatal_error      // see note (2) below
    };
    error_code   code() const;  // use this method to get an error code for the exception
    const_string what() const;  // use this method to get an error message for the exception
};
Note 1 :uncaught C++ exceptions 被当做 error,如果应用程序捕获到 C++ exception,则该 exception 不会到 boost::execution_monitor;
Note 2 :这些 error 包括 UNIX signals 和 Windows structured exceptions,这些经常由 hardware traps 触发。

execution_monitor 可以动态连接,库中没有提供 main 函数。由于只有一个 libs/test/execution_monitor.cpp 文件,因此可以直接 copy 该文件。
(http://yaekees.spaces.live.com/blog/cns!1955EE8C6707277A!148.entry)


boost Test 的 Program Execution Monitor

C++ program 可以通过 return value 和 throwing an exception 报告 user-detected errors,而如 dereferencing an invalid pointer 的 System-detected errors 则以其他方式报告。
 
Boost Test Library 的 Program Execution Monitor 减轻了用户处理复杂的 error detection 和 reporting,并提供了 main() 函数在 monitored environment 来调用用户提供的 cpp_main() 函数,main() 函数以一致的方式检测和报告多种 errors 的发生,将其转化为一致的 return code 返回给 host enviroment。
BOOST_TEST_CATCH_SYSTEM_ERRORS 设置允许 Execution Monitor 捕获 system errors,默认值为 "yes"。
BOOST_PRG_MON_CONFIRM 设置是否允许用户交互确认程序正确运行,默认值为"yes"。
 
Program Execution Monitor 使用 Execution Monitor 监视用户提供的 cpp_main() 函数的运行。尽管 Program Execution Monitor 在 libs/test/src/cpp_main.cpp 提供了 main() 函数,但是为了 link 正确,用户必须提供一个与 main() 函数一样接口的 cpp_main() 函数。如 cpp_main() 抛出异常或返回非 0 值,Program Execution Monitor 就认为程序发生错误。
Program Execution Monitor 在 cout 和 cerr 流上分别提供详细和简要的错误报告。Program Execution Monitor 提供的 main() 函数返回如下的值
1. boost::exit_success - no errors
2. boost::exit_failure - non-zero and non-boost::exit_success return code from cpp_main().
3. boost::exit_exception_failure - cpp_main() throw an exception.
(http://yaekees.spaces.live.com/blog/cns!1955EE8C6707277A!149.entry)


boost Test 的 Test Tools

Test Tools 为了让用户使用方便,提供了一系列的宏,这些宏分三级,其效果是不同的:
WARN 不增加引用计数,继续执行程序
CHECK 增加应用计数,继续执行程序
REQUIRE 增加应用计数,中断程序的运行
 
使用 CHECK level tools 实现 assertions,使用 WARN level tools 检验不太重要但是正确的方面,如:性能、可移植性、有用性,如 assertions 失败就不应该让程序继续运行则使用 REQUIRE level tools。
 
Test Tools 提供了两个 .hpp 文件 boost/test/test_tools.hpp 和 boost/test/floating_point_comparison.hpp,一个 .cpp 文件 libs/test/test_tools.cpp
BOOST_WARN( P )
BOOST_CHECK( P )
BOOST_REQUIRE( P )
BOOST_WARN_MESSAGE( P, M )
BOOST_CHECK_MESSAGE( P, M )
BOOST_REQUIRE_MESSAGE( P, M )
BOOST_ERROR( M )BOOST_FAIL( M )
BOOST_MESSAGE( M )
BOOST_CHECKPOINT( M )
BOOST_WARN_THROW( S, E )
BOOST_CHECK_THROW( S, E )
BOOST_REQUIRE_THROW( S, E )
BOOST_WARN_EXCEPTION( S, E, P )
BOOST_CHECK_EXCEPTION( S, E, P )
BOOST_REQUIRE_EXCEPTION( S, E, P )
BOOST_IGNORE_CHECK( e )
BOOST_WARN_NO_THROW( S )
BOOST_CHECK_NO_THROW( S )
BOOST_REQUIRE_NO_THROW( S )
BOOST_WARN_CLOSE( L, R, T )
BOOST_CHECK_CLOSE( L, R, T )
BOOST_REQUIRE_CLOSE( L, R, T )
BOOST_WARN_SMALL( FPV, T )
BOOST_CHECK_SMALL( FPV, T )
BOOST_REQUIRE_SMALL( FPV, T )
BOOST_WARN_PREDICATE( P, ARGS )
BOOST_CHECK_PREDICATE( P, ARGS )
BOOST_REQUIRE_PREDICATE( P, ARGS )
BOOST_WARN_EQUAL_COLLECTIONS( L_begin, L_end, R_begin, R_end )
BOOST_CHECK_EQUAL_COLLECTIONS( L_begin, L_end, R_begin, R_end )
BOOST_REQUIRE_EQUAL_COLLECTIONS( L_begin, L_end, R_begin, R_end )
BOOST_WARN_BITWISE_EQUAL( L, R )
BOOST_CHECK_BITWISE_EQUAL( L, R )
BOOST_REQUIRE_BITWISE_EQUAL( L, R )
BOOST_IS_DEFINED( symb )
BOOST_BITWISE_EQUAL( L, R )
(http://yaekees.spaces.live.com/blog/cns!1955EE8C6707277A!145.entry)


boost Test 的 Test Execution Monitor

Test Execution Monitor 结合了 Test Tools 和 Execution Monitor 的特点简化了烦琐测试工作,它提供了 main() 函数调用用户提供的 test_main() 函数,用户可以使用 Test Tools 来进行复杂的验证工作。
 
Test Execution Monitor 被设计用来进行测试简单的程序或者从已存在的 production code 中 dig a problem。Program Execution Monitor 更适合监控 production (non-test) programs(因为它不影响程序的性能),而 Unit Test Framework 更适合 complex test programs,因为 Unit Test Framework 可以
1. 可以将 test 分割到多个 test cases,它会为每一个 test case 分别产生 pass/fail 的统计信息;
2. 假如某一个 test case 失败了不会影响其他的 test;
3. 可以通过指定 name 来运行特定的 test case
4. 分离的 test cases 运行更清楚发现特定测试模块的目的
5. 可以设置更多的选项
(http://yaekees.spaces.live.com/blog/cns!1955ee8c6707277a!150.entry)


boost Test 的 Unit Test Framework

regression testing 只关注程序运行的时候是否有错误发生,而 unit test 则需要尽可能详细的输出错误的信息。Unit Test Framework 用 test tools 简化了 test cases 的编写并将其组织为有层次的 test suites。它提供了 main() 函数初始化 framework,通过命令行参数或者是环境变量设置参数,并通过 init_unit_test_suite(argc, argv),然后运行用户的 test suite。Framework 跟踪所有的 passed/failed 的 Test Tools assertions,可以通过 test cases 的数目(part 和 total)得到测试进度,并且可以多种形式提供结果。Unit Test Framework 可被用来进行简单测试和复杂重要测试,它不适合用在 production code,同时它以运行时的效率为代价加速编译。
 
该函数负责创建和初始化顶层的 test_suite 实例,如 test_suite 创建失败该函数返回 NULL 指针,测试终止并返回一个 boost::exit_test_failure。Framework 在测试运行时传递特定的命令行参数,同时排斥其他 framework 指定的参数,同时 framework 负责 test_suite 的生命周期,在 test 终止时会被销毁。
 
假如 test cases 会丢出自定义的异常,可以像 Execution Monitor 那样注册特定的 translator,注册函数的原型定义如下
template<typename Exception, typename ExceptionTranslator>
void boost::unit_test::register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* d = 0 )
 
一旦测试结束,framework 会报告结果并返回 return code。下面是集成在 unit test framework 内部的的返回值
boost::exit_success  returned if no errors occurred during test or success result code was explicitly requested with the no result code framework parameter
boost::exit_test_failure  returned if nonfatal errors detected and no uncaught exceptions thrown or the framework fails to initialize the test suite
boost::exit_exception_failure  returned if fatal errors detected or uncaught exceptions thrown
 
在 VC7.1+stlport 4.62 上 unit_test_example3.cpp 没有通过(对多种继承没有通过)
 
简单的使用方法:
1. 首先定义 #define BOOST_AUTO_TEST_MAIN
2. 包含 #include <boost/test/auto_unit_test.hpp>
3. 创建一个 test_suite
BOOST_AUTO_TEST_CASE( test )
{
    BOOST_CHECK( true );
}
然后 link libboost_test_exec_monitor-vc71-mt-sp-1_33.lib 就可以了。
 
另一类使用方法,首先包含如下
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_monitor.hpp>
using namespace boost::unit_test;
然后声明 test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) {}
一个典型用法是
test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) {
    test_suite* test = BOOST_TEST_SUITE("custom_exception_test");
    unit_test_monitor.register_exception_translator<my_exception1>( &my_exception1_translator );
    unit_test_monitor.register_exception_translator<my_exception2>( &my_exception2_translator );
    test->add( BOOST_TEST_CASE( &throw_my_exception1 ) );
    test->add( BOOST_TEST_CASE( &throw_my_exception2 ) );
    return test;
}
(http://yaekees.spaces.live.com/blog/cns!1955EE8C6707277A!151.entry)


boost 的 minimal testing facility

只适合使用在 test environment 中,不需要 link 任何外部的组件。用户只需要提供了如下的函数
int test_main( int argc, char* argv[] ) 就可以了。minimal testing facility 提供了 BOOST_CHECK(predicate),BOOST_REQUIRE(predicate),BOOST_ERROR(message), BOOST_FAIL(message)。除了这四个 MACRO 以外可以通过抛出异常和 return 返回值报告错误。下面是 boost 提供的一个示例。
#include <boost/test/minimal.hpp>
int add( int i, int j ) { return i+j; }
int test_main( int, char *[] )             // note the name!
{
    // six 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 "Oops..."; // #5 throws on error
    return add( 2, 2 ) == 4 ? 0 : 1;       // #6 returns error code
}
BOOST_CHECK 如果该表达式失败了,会出现源代码文件名、代码行号、并且会增加 error count,一旦程序终止 error count 会显示在 std::cout;
BOOST_REQUIRE 类似于 BOOST_CHECK,但是会抛出被  Minimal testing facility 捕获的异常。
(http://yaekees.spaces.live.com/blog/cns!1955EE8C6707277A!147.entry)

posted on 2008-03-29 15:39 不倦 阅读(3290) 评论(1)  编辑 收藏 引用 所属分类: C++单元测试框架

评论

# re: [转]Boost Test Library  回复  更多评论   

不错不错 很受教啊
美中不足的是具体的例子举的太少了
2008-06-12 11:07 | jazz

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理