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

时间:2011-04-21 06:01:18

标签: c unit-testing stdin

我将以下职能作为大学任务的一部分:

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(就像我一样),因为我教授提出了许多要求。

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

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

3 个答案:

答案 0 :(得分:5)

可以做的一件事就是简单地修改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;
}

然后,要从单元测试中调用它,您可以执行以下操作:

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

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

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

答案 1 :(得分:1)

查找非标准但非常有用的函数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 */
}

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

答案 2 :(得分:0)

为什么不能使用重定向?类似的东西:

./a.out < input.txt

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