C中exit()的单元测试

时间:2019-01-17 03:36:31

标签: c exit cunit

我正在使用CUnit框架显示测试结果的方式。 (我是一名编程与S.O.新手,因此非常感谢您一步一步的回答)。

在测试我希望退出的函数时,是否可以使用相同的CUnit框架?在我看来,情况并非如此,但无论如何我还是很想问-它会显示通过/失败结果以及其他CUnit测试,因此非常理想。

如果没有,我一直在寻找其他友好型解决方案(例如this SO post),但是我不能使用GOTO / setjmp / longjmp。该解决方案还需要具有可移植性。

我正在使用Mac&gcc命令行运行此代码。

编辑 建议的解决方案之一是使用C预处理程序(CPP)指令/ "mocking",哪个看起来很理想?我在test.c文件中使用了以下代码:

#define ERROR(PHRASE) {fprintf(stderr,"Fatal Error %s occurred in %s, line %d\n",PHRASE, FILE, LINE); exit(2);} 
#ifdef ERROR(PHRASE)
#define ERROR(PHRASE) {printf("In test phase");} 
#endif 
#ifndef ERROR(PHRASE #define ERROR(PHRASE) {printf("Not In test phase");} 
#endif

这是终端给我的错误消息:

test.c:30:9: warning: 'ERROR' macro redefined [-Wmacro-redefined]
#define ERROR(PHRASE) {printf("In test phase");}
        ^
test.c:26:9: note: previous definition is here
#define ERROR(PHRASE) {fprintf(stderr,"Fatal Error %s occured in %s, lin...
        ^
test.c:32:14: warning: extra tokens at end of #ifndef directive
      [-Wextra-tokens]
#ifndef ERROR(PHRASE) {printf("Not In test phase");}

删除(PHRASE)仍然会出现相同的错误。

编辑 如果对其他人有帮助,那么使用#ifdef进行模拟是最终解决此问题的最简单方法。 This website也很有帮助。

3 个答案:

答案 0 :(得分:1)

这样您就知道要搜索什么,您想要做的就是“模拟” exit()调用。基本思想是通常在编译时为退出函数选择不同的实现。坦白说,C并不是特别容易实现,但是有些选项具有不同程度的可移植性和侵入性。

This article描述的东西很容易移植,但也很侵入。基本上,您使用宏和/或函数指针来回切换,这意味着要稍微修改一下代码,但是说实话,这没什么大不了的。

对于某些可能不太侵入但也不太便携的东西,this article有几个想法(我相信两者都可以在MacOS上使用)。在这里,您将获得链接程序,以将exit()调用重定向到您提供的另一个函数。好消息是它不需要对代码进行任何修改。坏消息是它要求您获得链接器的合作,并且不能在任何地方使用(LD_PRELOAD在Windows上不可用,并且AFAIK --wrap需要GNU ld或兼容的东西)。

答案 1 :(得分:0)

如果在测试方面有问题/需要付出更多的努力,可以考虑的一个方面是,是否有任何范围可以某种方式更改要测试的程序,这将有助于测试而又不会显着增加代码的复杂性。

在这种情况下,是否存在用函数的错误返回代码替换对exit()的调用的范围,从而使调用者可以在实际退出之前进行整理或记录状态之类的操作?如果是这样,这既简化了测试,又可能简化了在发行/生产中实际使用代码时的故障查找,因为弄清楚为什么程序只是在您身上死掉是很棘手的,特别是如果代码是隐藏在库函数中!

答案 2 :(得分:0)

如果你想做一些非侵入性的事情,你可以将被测函数作为一个单独的进程运行。您以 CreateProcess (Windows) 或 fork(在 Max 和 Linux 上可能还有 execv)开始。然后您的测试代码使用 wait 测试退出代码并通过创建的进程正确退出。