如何为另一个使用stdin输入的函数编写测试函数?

作为大学任务的一部分,我有以下function:

int readMenuOption() { /* local declarations */ char option[2]; /* read in 1 char from stdin plus 1 char for string termination character */ readStdin(1 + 1, option); return (int)option[0] <= ASCII_OFFSET ? 0 : (int)option[0] - ASCII_OFFSET; } int readStdin(int limit, char *buffer) { char c; int i = 0; int read = FALSE; while ((c = fgetc(stdin)) != '\n') { /* if the input string buffer has already reached it maximum limit, then abandon any other excess characters. */ if (i <= limit) { *(buffer + i) = c; i++; read = TRUE; } } /* clear the remaining elements of the input buffer with a null character. */ for (i = i; i < strlen(buffer); i++) { *(buffer + i) = '\0'; } return read; } 

它完美适用于我需要它做的事情(从键盘输入)。 我必须使用stdin(就像我一样),因为我的教授提出了许多要求。

我想为赋值编写一系列“unit testing”,但我不知道如何让我的测试函数调用readMenuOption()并将输入传递给它(无需在运行时执行)。

这是可能的,如果是的话,我该怎么做? (即,是否可以写入标准输入)?

可以做的一件事就是简单地修改readStdin以允许它从真正的标准输入或辅助函数中获取数据,例如:

 char *fakeStdIn = ""; int myfgetc (FILE *fin) { if (*fakeStdIn == '\0') return fgetc (fin); return *fakeStdIn++; } int readStdin(int limit, char *buffer) { char c; int i = 0; int read = FALSE; while ((c = myfgetc(stdin)) != '\n') { /* if the input string buffer has already reached it maximum limit, then abandon any other excess characters. */ if (i <= limit) { *(buffer + i) = c; i++; read = TRUE; } } /* clear the remaining elements of the input buffer with a null character. */ for (i = i; i < strlen(buffer); i++) { *(buffer + i) = '\0'; } return read; } 

然后,要从unit testing中调用它,您可以执行以下操作:

 fakeStdIn = "1\npaxdiablo\nnice guy\n"; // Call your top-level input functions like readMenuOption(). 

通过在较低级别放置一个钩子,您可以注入自己的字符序列而不是使用标准输入。 如果在任何时候,假标准输入已经用完,它将恢复为真实标准输入。

显然,这是使用字符,所以,如果你想要注入EOF事件,你需要一个整数数组,但这将是对该方案的一个小修改。

查找非标准但非常有用的函数forkpty 。 然后做一些事情:

 int ptyfd; pid = forkpty(&ptyfd, 0, 0, 0); if (pid<0) perror("forkpty"), exit(1); if (!pid) { /* call your function to be tested */ _exit(1); } else { /* write to ptyfd here to generate input for the function */ } 

请注意,这将允许您测试您的function,就像从交互式终端读取一样。 如果您不需要该级别的测试,则可以使用简单的管道。

为什么不能使用重定向? 就像是:

 ./a.out < input.txt 

其中“input.txt”将包含您要为程序提供的任何输入。