我熟悉标准 C++ 断言的工作原理。这在我的项目中运行良好,可用于各种测试目的。
例如,假设我想检查我的代码是否引发了某个异常。
如果不使用像 CPPUnit 这样的测试框架,这可能吗?
您可以手动执行CPPUnit执行的相同操作:
bool exceptionThrown = false;
try
{
// your code
}
catch(ExceptionType&) // special exception type
{
exceptionThrown = true;
}
catch(...) // or any exception at all
{
exceptionThrown = true;
}
assert(exceptionThrown); // or whatever else you want to do
当然,如果您经常使用这种模式,那么为此使用宏是有意义的。
骨架(未测试)
#define MY_ASSERT(f, e) {\
try {\
f();\
} catch (std::exception &e) {\
...\
}\
}
这是我根据@JPlatte 和@gongzhitaao 的回答编写的异常测试器。对于我的测试框架,我有两个全局变量num_test
,num_test_success
用于跟踪执行了多少测试以及在一系列测试中成功了多少,但这可以根据您的需要进行更改。
int num_test;
int num_test_success;
#define UT_ASSERT_THROW(expression, ExceptionType) { \
\
try { \
expression; \
printf("test %d: *** FAILURE *** %s:%d:%s,%s\n", \
num_test, __FILE__, __LINE__, \
#expression, #ExceptionType); \
} catch (const ExceptionType &) { \
printf("test %d: success\n", num_test); \
++num_test_success; \
} catch (...) { \
printf("test %d: *** FAILURE *** %s:%d:%s,%s\n", \
num_test, __FILE__, __LINE__, \
#expression, #ExceptionType); \
} \
\
++num_test; \
\
}
宏__FILE__
并__LINE__
扩展为当前文件和行号(请参阅https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html)。宏内部的井号告诉预处理器将参数作为字符串放入宏扩展中(参见http://bruceblinn.com/linuxinfo/Stringification.html)。
代码内断言通常用于方法的开头,以确认在进入此特定功能之前满足某些先决条件,例如:
Window::paint()
{
assert(m_device != NULL);
m_device->repaintRegion();
}
它们在这里主要是为了捕捉方法或类之间未满足的依赖关系的错误。
测试框架中的断言是不同的,通常用于单元测试,以确保单元返回它需要返回的任何内容。
通常应该在现实(即外部系统)为我们提供代码不能/不应该处理的情况下抛出异常。这是解决罕见但仍可预期的问题的简单方法。例如 - 等待服务器通常可用的超时。或者,内存不足。我不会将它用作编程逻辑的辅助工具。
对于您的问题,可能有一种方法可以通过使用 try-catch 包围测试的单元来捕获测试框架中的异常。但我不确定它是否真的可取。
高温高压