Search code examples
c++unit-testingboost-test

BOOST_CHECK_NO_THROW how to get exception message printed


When I test a method using

BOOST_CHECK_NO_THROW( method_to_test() );

and an exception is thrown, it displays that an exception was thrown, but never the exception's message like this:

test.cpp(14): error in "test": incorrect exception my_exception is caught

Is it possible to print the exception message as well, i.e. the string returned by my_exception.what()? my_exception is derived from std::exception and overloads what().


Solution

  • I read a bit in the boost headers and redefined BOOST_CHECK_NO_THROW_IMPL in my own header file I use in the project to redefine the boost behavior. Now it looks like this:

    #ifndef _CATCH_BOOST_NO_THROW_H_
    #define _CATCH_BOOST_NO_THROW_H_  
    
    #include <boost/test/unit_test.hpp>
    #include <sstream>
    #include <string>
    
    #define BOOST_CHECK_NO_THROW_IMPL( S, TL )                                                      \
        try {                                                                                       \
        S;                                                                                          \
        BOOST_CHECK_IMPL( true, "no exceptions thrown by " BOOST_STRINGIZE( S ), TL, CHECK_MSG ); } \
        catch( const std::exception & e ) {                                                         \
        std::stringstream ss;                                                                       \
        ss << std::endl                                                                             \
        << "-----------------------------------------------" << std::endl                           \
        << "test case: " << boost::unit_test::framework::current_test_case().p_name << std::endl    \
        << std::endl << "exception message: " << e.what() << std::endl;                             \
        BOOST_TEST_MESSAGE(ss.str());                                                               \
        BOOST_CHECK_IMPL( false, "exception thrown by " BOOST_STRINGIZE( S ), TL, CHECK_MSG );      \
        }                                                                                           \
        catch( ... ) {                                                                              \
        std::stringstream ss;                                                                       \
        ss << std::endl                                                                             \
        << "-----------------------------------------------" << std::endl                           \
        << "test case: " << boost::unit_test::framework::current_test_case().p_name << std::endl    \
        << std::endl << "exception message : <unknown exception>" << std::endl;                     \
        BOOST_TEST_MESSAGE(ss.str());                                                               \
        BOOST_CHECK_IMPL( false, "exception thrown by " BOOST_STRINGIZE( S ), TL, CHECK_MSG );      \
        }                                                                                           \
        /**/
    
    #define BOOST_WARN_NO_THROW( S )            BOOST_CHECK_NO_THROW_IMPL( S, WARN )
    #define BOOST_CHECK_NO_THROW( S )           BOOST_CHECK_NO_THROW_IMPL( S, CHECK )
    #define BOOST_REQUIRE_NO_THROW( S )         BOOST_CHECK_NO_THROW_IMPL( S, REQUIRE )
    
    #endif // _CATCH_BOOST_NO_THROW_H_
    

    The disadvantages are: It works as long as there are no changes in BOOST_*_NO_THROW

    and

    the exception message will be printed before it is marked as error in the test output. That looks in the first place a bit pitty, that's why I group the output by writing "---" to the outstream to enhance the reading. But code after BOOST_CHECK_IMPL will never be reached.

    The solution above work quite nice for me. Feel free to use to, if you got the same whish =)

    (Using CDash for ctest output, don't forget to increase the test output limit, or simple disable the limit: http://web.archiveorange.com/archive/v/5y7PkVuHtkmVcf7jiWol )