这是我想要的情景。我正在测试的函数有一个错误条件,如果命中,调用一个优雅的退出函数来释放任何全局内存、关闭句柄和退出程序。
显然,我想要编写一个测试,它勾起了这个条件,以确保它被正确地处理,但我不希望优雅的退出例程实际上退出程序,因为这将停止任何剩余的测试。这意味着坚持优雅的退出程序。顽固性和不调用exit的问题是,控制流返回到正在测试的函数(这是不好的,因为例程应该退出)。
下面是实际的问题:如何将控制从存根函数返回到测试,而不是返回到测试中的函数?
我可以做一个setjmp / longjmp,但是由于"gotos“总的来说是不好的,所以我喜欢其他的建议。(请记住,这是过程C,而不是C++,因此据我所知,异常不会起作用)
正如索伦和其他人所建议的那样,编辑,当测试是一个好主意时,让exit什么也不做。有几种方法可以做到这一点,无论是通过exit()例程的#define语句还是存根。
然而,这样做带来的问题是,我真正想要的是一个解决方案( setjmp /longjmp除外)。看一看这个场景:
void gracefulExit() {
// Clean Up
exit();
}
void routineUnderTest() {
// Do some calcs
if (someBadCondition == TRUE)
gracefulExit()
// Do some more calcs
}
如果exit()在这个场景中什么也不做,gracefulExit()将把控制返回到测试中的例程,这是不应该发生的。因此,我需要一种使exit() (或gracefulExit()的短尾版本)返回到测试而不是测试中的函数的控制的方法。
setjmp / longjmp (又名goto)是这样做的一种方法,尽管并不是一种真正的优雅方式。对如何解决这个问题有什么想法吗?
编辑#2
正如fizzer所提到的,setjmp/longjmp是处理这种情况的有效方法。这可能是我将永久处理它的方式。
然而,我从一位同事那里得到了另一个可能的解决方案。不要将gracefulExit()例程定义为存根例程,而是执行以下操作:
#define gracefulExit return NULL
测试中的特定函数可以很好地处理这一点,因为NULL是它的有效返回值。我还没有在所有可能的情况下测试这一点(例如,具有空返回值的函数)。正如前面提到的,我可能会使用setjmp/longjmp方法来解决这个问题,但是如果这个附加的解决方案激发了某个人的想法,那就太好了!
发布于 2011-08-01 14:27:54
我使用setjmp / longjmp (包装在一个方便的宏中)来处理这个和类似的场景(例如,测试断言失败)。
发布于 2011-08-01 14:39:26
我建议您的清理方法创建一个未发布的接口来执行退出操作。
所以
void (*exitfunc((int) = exit;
void myCleanUp() {
.... do the cleanup
(*exitfunc)(-1); // this will in normal operation call exit
}
在单元测试代码中,您“覆盖”退出函数,如
void donothing(int exitcode) {}
unittest(){
extern void (*exitfunc((int);
exitfunc = donothing; // or use a longjump if clean exit cannot be made without
... do the test.....
这意味着,无论是在单元测试中还是在其他地方,代码都会编译成相同的代码,而且只有在执行单元测试时才会出现行为上的差异。为单元测试使用条件编译的替代方法意味着,您将得到.o文件,您不知道这些文件是用于测试还是用于生产,并且您的项目会发生一些不好的事情。
发布于 2011-08-01 18:20:17
如果您的平台支持弱符号,您可以通过使用弱符号来实现这一点。
您将编写两个版本的graceful_exit()
函数,一个被定义为弱符号的普通应用程序使用,另一个在正常定义的单元测试框架下运行时使用。
这样做的意图是,如果您正在针对单元测试代码进行链接,则函数的强版本将被使用而不是弱版本。
这样做的好处是不需要有条件的编译来支持单元测试。
对于this问题中弱符号的使用进行了有益的讨论。
https://stackoverflow.com/questions/6904769
复制相似问题