C++ BOOST\u CHECK\u NO\u抛出如何打印异常消息
当我使用C++ BOOST\u CHECK\u NO\u抛出如何打印异常消息,c++,unit-testing,boost-test,C++,Unit Testing,Boost Test,当我使用 BOOST_CHECK_NO_THROW( method_to_test() ); 当抛出异常时,它会显示抛出了异常,但不会显示如下异常消息: test.cpp(14): error in "test": incorrect exception my_exception is caught #ifndef _CATCH_BOOST_NO_THROW_H_ #define _CATCH_BOOST_NO_THROW_H_ #include <boost/test/unit
BOOST_CHECK_NO_THROW( method_to_test() );
当抛出异常时,它会显示抛出了异常,但不会显示如下异常消息:
test.cpp(14): error in "test": incorrect exception my_exception is caught
#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_
BOOST_AUTO_TEST_CASE(case2)
{
BOOST_CHECK_NO_THROW( makeDecorator(method_to_test)(0) );
BOOST_CHECK_NO_THROW( makeDecorator(another_method_to_test)() );
}
是否也可以打印异常消息,即
my_exception.what()
返回的字符串my_exception
源于std::exception
和重载what()
我发现自己对BOOST\u REQUIRE\u NO\u THROW
的同样问题感到恼火。我通过简单地删除BOOST\u REQUIRE\u NO\u THROW
解决了这个问题。这将产生如下输出:
unknown location(0): fatal error in "TestName": std::runtime_error: Exception message
并中止测试(但继续下一个文本),这正是我想要的。但是,如果您想使用BOOST\u CHECK\u NO\u THROW或BOOST\u WARN\u NO\u THROW,这没有多大帮助。我在BOOST头文件中读了一些内容,并在我自己的头文件中重新定义了BOOST\u CHECK\u NO\u THROW\u IMPL,我在项目中使用它来重新定义BOOST行为。现在看起来是这样的:
test.cpp(14): error in "test": incorrect exception my_exception is caught
#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_
BOOST_AUTO_TEST_CASE(case2)
{
BOOST_CHECK_NO_THROW( makeDecorator(method_to_test)(0) );
BOOST_CHECK_NO_THROW( makeDecorator(another_method_to_test)() );
}
\ifndef\u捕获\u提升\u否\u抛出\H_
#定义"接球","助攻","否","掷球"
#包括
#包括
#包括
#定义增压、检查、否抛出、执行(S、TL)\
试试{\
S\
BOOST_CHECK_IMPL(true,“BOOST_STRINGIZE,TL,CHECK_MSG);”不会引发异常\
catch(const std::exception&e){\
std::stringstream-ss\
ss解决方案1。
使用捕获异常的包装器方法,然后打印错误消息,然后重新抛出,以便BOOST
可以报告它:
void method_to_test(int s)
{
if(s==0)
throw std::runtime_error("My error message");
}
void middle_man(int x)
{
try
{
method_to_test(x);
}catch(std::exception& e)
{
std::stringstream mes;
mes << "Exception thrown: " << e.what();
BOOST_TEST_MESSAGE(mes.str());// BOOST_ERROR(mes.str());
throw;
}
}
这种方法的一个缺点是,对于每个测试方法
,您都需要使用不同的中间人
函数
解决方案2。
使用装饰器,看这个,
来完成前一个解决方案中的包装器所能做的事情
template <class> struct Decorator;
template<class R,class ... Args>
struct Decorator<R(Args ...)>
{
std::function<R(Args ...)> f_;
Decorator(std::function<R(Args ...)> f):
f_{f}
{}
R operator()(Args ... args)
{
try
{
f_(args...);
}catch(std::exception& e)
{
std::stringstream mes;
mes << "Exception thrown: " << e.what();
BOOST_TEST_MESSAGE(mes.str());
throw;
}
}
};
template<class R,class ... Args>
Decorator<R(Args...)> makeDecorator(R (*f)(Args ...))
{
return Decorator<R(Args...)>(std::function<R(Args...)>(f));
}
写入到何处?Boost测试用于检查代码是否已损坏,而不是调试代码。是否已损坏?它是布尔值:true或false。(1)写入标准输出(控制台或xml文件,取决于测试运行程序的命令行参数)(2)如果引发异常,则是已损坏。但如果可以看到异常消息(what()的输出)找出错误的来源更快。是的,但为什么?测试确实表明代码被破坏了:它会在不应该抛出的地方抛出异常。下一步是采取措施并修复代码或测试,而不是创建用垃圾填充控制台的详细XML文件。嗯,好的。我认为更快地找到错误会很好。我的测试使用了db(在现实中,没有模拟对象)和测试可能会因为不同的原因而失败(不仅仅是因为错误的类或测试代码)。我相信“高度可定制”的boost测试框架可能会有一个解决方案,但我可能最终不使用这个漂亮的boost\u AUTO.*()
。但是谢谢你,蒂布!为什么,@Ö蒂布?你宁愿让你的医生告诉你“我发现你有问题。”还是“我发现你的膝盖有问题。”?如果语句没有包装在BOOST\uu\u NO\u THROW
中,单元测试框架会打印异常消息。使用断言不会比没有断言时提供更少的信息。奇怪的是,这对我来说是最好的解决方案。