2011-04-21 90 views
3

我有以下功能作为学院任务的一部分:如何为使用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()并将输入传递给它(而不必在运行时执行)。

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

+0

可能重复[如何单元测试涉及IO的c函数?](http://stackoverflow.com/questions/14028950/how-to-unit-test-c-functions-involving-io) – Valryne 2015-10-04 13:15:59

回答

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事件,你需要一个整数数组来代替,但这只是对方案的一个小修改。

+0

完美无瑕! – Ash 2011-04-21 07:24:20

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

请注意,这将允许您像测试交互式终端一样测试您的功能。如果你不需要这个级别的测试,你可以用一个简单的管道代替。

0

为什么你不能使用重定向?例如:

./a.out < input.txt 

其中“input.txt”将包含任何要输入到程序中的输入。

相关问题