【问题标题】:How to unit test c functions involving IO?如何对涉及 IO 的 c 函数进行单元测试?
【发布时间】:2012-12-11 07:47:33
【问题描述】:

我在为涉及 IO 操作的 C 函数编写单元测试时遇到问题。例如,下面是我编写的从控制台获取用户输入字符串的代码。我不知道如何使用 getchar() 函数自动测试用户输入。

char * GetStringFromConsole()
{

    char *strToReturn = NULL;
    int len = 128;

    strToReturn = (char*)malloc(len);
    if (strToReturn) 
    {
        int ch;
        char *ptr  = strToReturn;
        int counter = 0;
        for (; ;) 
        {
            ch = getchar();
            counter++;

            if (counter == len)
            {
                strToReturn = realloc(strToReturn, len*=2 );
                ptr = strToReturn + counter-1;
            }

            if ((ch != EOF) && (ch != '\n') && (counter < len))
            {
                *ptr++ = ch;
            }
            else 
            {
                break;
            }

        }
        *ptr = '\0';
    }
    return strToReturn;
}   

【问题讨论】:

  • 您可以制作一个 shell 脚本来运行您的程序并将其输出与一些预期的内容进行比较。

标签: c unit-testing io mocking getchar


【解决方案1】:

模拟getchar:

  1. 使用预处理器,例如在您的测试文件中。

    #define getchar mock_getchar
    #include "GetStringFromConsole.h"
    ...
    const char* mock_getchar_data_ptr;
    char mock_getchar()
    {
        return *mock_getchar_data_ptr++;
    }
    ...
    // in test function
    mock_getchar_data_ptr = "hello!\n";
    YourAssertEquals("hello", GetStringFromConsole());
    
  2. 链接器的替换符号(在我看来更难),例如在源 .c 文件中的某处定义您自己的 getchar,而不是链接到 stdlib(例如 Windows 上的 msvcrt)

  3. 修改被测函数以接受返回 char 的函数,最佳选择(恕我直言) - 与 stdlib 没有冲突。并通过在测试代码中从点 1 传递类似 mock_getchar 的东西来设置测试。

    typedef char (*getchartype)();
    char * GetStringFromConsole(getchartype mygetchar)
    {
        ...
        c  = mygetchar()
    

对于 1 和 2 点,我建议使用您自己的函数而不是 getchar(例如 mygetchar) - 这样您就可以模拟/替换它不会与 std 包含/库发生冲突。

【讨论】:

  • cmocka 单元测试框架支持模拟对象,并展示了如何使用模拟函数覆盖原始函数。点击了解更多cmocka.org
猜你喜欢
  • 2017-08-19
  • 2014-06-27
  • 2012-01-11
  • 2021-03-02
  • 1970-01-01
  • 2021-08-02
  • 2013-05-27
  • 2014-02-08
  • 2021-12-03
相关资源
最近更新 更多