【发布时间】:2020-10-05 17:24:50
【问题描述】:
我正在为个人项目编写一个动态数组,并尝试对所有功能进行单元测试。我正在尝试为util_dyn_array_check_index() 编写单元测试,但这样做时遇到了问题,因为如果索引超出范围,我做出了调用exit(-1) 的设计决定。我想检查我的单元测试,它在提供无效索引时调用exit()。但是如果我给它一个无效的索引,它就会退出我的测试程序。是否有可能以某种方式捕获对exit() 的调用,或者在我的测试程序中重新定义exit() 以防止它结束测试?
来自this answer,我查看了atexit(),但它看起来并没有停止退出,只是在退出之前执行一个或多个用户定义的函数。这对我不起作用,因为在此之后我还有其他测试要运行。我最后的想法是我可以将util_dyn_array_check_index() 设为宏而不是函数,并将exit() 重新定义为我的测试程序中的不同函数,但如果可以避免,我宁愿不将其设为宏。
这是我的代码:
这个结构的细节并不重要,只是为了完整性而提供的
//basically a Vec<T>
typedef struct {
//a pointer to the data stored
void * data;
//the width of the elements to be stored in bytes
size_t stride;
//the number of elements stored
size_t len;
//the number of elements able to be stored without reallocating
size_t capacity;
} util_dyn_array;
这是我要测试的功能。
//exits with -1 if index is out of bounds
inline void util_dyn_array_check_index(util_dyn_array * self, size_t index) {
if (index >= self->len) {
exit(-1);
}
return;
}
这是我想要的测试框架(为了清楚起见,省略了我用来使编写测试更好的一些宏魔法)。
bool test_dyn_array_check_index() {
util_dyn_array vector = util_dyn_array_new(sizeof(int), 16);
for(int i = 0; i < 16; i++) {
util_dyn_array_push(&vector, (void*)&i);
}
for(int i = 0; i < 16; i++) {
//if nothing happens, its successful
util_dyn_array_check_index(&vector, i);
}
//somehow check that it calls exit without letting it crash my program
{
util_dyn_array_check_index(&vector, 16);
}
return true;
}
显然我可以更改我的代码以返回 bool 或写入 errno,但我希望它退出,因为它通常是一个不可恢复的错误。
【问题讨论】:
-
这通常通过重新设计单元测试调用来处理,以便每个单元测试都作为自己的二进制文件/进程运行,尤其是因为它也会捕获崩溃。
-
这是有道理的。有什么建议可以在哪里学习如何做到这一点,或者要搜索什么?
-
请指定您的操作系统和工具链,因为
exit()之后发生的任何事情都超出了标准 C 的范围。例如,在 Unix 上,您可以使用fork()在孩子中运行测试过程。 -
运行 MacOS Catalina、Clang 11.0.3 和 c11
-
在大多数(全部?)现代 Unix 系统上,您只需定义自己的
exit()函数,该函数将覆盖标准 C 库中的弱符号。例如。void exit(int s){ for(;;) printf("tits\n"); }。将其放入 C 文件中,然后将其静态或动态链接到您的代码。这不会覆盖在 main() 返回后调用的隐式 exit(),也不会覆盖 C 库内部的任何 exit() 调用。
标签: c unit-testing exit