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

发布于 2024-11-02 18:57:13 字数 1051 浏览 5 评论 0原文

作为大学作业的一部分,我具有以下功能:

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;
}

它非常适合我需要它做的事情(从键盘接收输入)。由于我的教授概述了许多要求,我必须使用标准输入(就像我一样)来完成此操作。

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

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

I have the following functions as part of a college assignment:

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;
}

It works perfectly for what I need it to do (take in input from keyboard). I've had to do it using stdin (like I have) because of a number of requirements outlined by my professor.

I want to write a series of "unit tests" for the assignment, but I dont know how to get my testing functions to call readMenuOption() and pass in input to it (without having to do it at run-time).

Is this possible, and if so, how can I do it? (i.e., is it possible to write to stdin)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半透明的墙 2024-11-09 18:57:13

可以做的一件事就是简单地修改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 事件,则需要一个整数数组,但这只是对该方案的一个微小修改。

One thing you could do is to simply modify readStdin to allow it to either get data from the real standard input, or from a helper function, something like:

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;
}

Then, to call it from your unit test, you can do:

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

By putting a hook at the lower levels, you can inject your own character sequence instead of using standard input. And if, at any point, the fake standard input is exhausted, it reverts to the real one.

Obviously, this is using characters so, if you want to inject EOF events, you'll need an array of integers instead, but that would be a minor modification to the scheme.

︶ ̄淡然 2024-11-09 18:57:13

为什么不能使用重定向?类似于:

./a.out < input.txt

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

Why can't you use redirection? Something like:

./a.out < input.txt

Where "input.txt" will contain whatever input you want to give to the program.

哥,最终变帅啦 2024-11-09 18:57:13

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

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

Lookup the nonstandard but extremely useful function forkpty. Then do something like:

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 */
}

Note that this will allow you to test your function exactly as if it were reading from an interactive terminal. If you don't need that level of testing, you could use a simple pipe instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文