Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test c functions involving IO?

I am facing problems in writing unit tests to C functions which involve IO operation. For example, below is the code I wrote to get an input string from the user from console. I do not know as to how to automate testing user input using getchar() function.

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;
}   
like image 774
ramkumarhn Avatar asked Dec 25 '12 08:12

ramkumarhn


People also ask

What is unit testing in C?

Unit testing only requires "cut-planes" or boundaries at which testing can be done. It is quite straightforward to test C functions which do not call other functions, or which call only other functions that are also tested. Some examples of this are functions which perform calculations or logic operations, and are functional in nature.

What is a unit test in Java?

A unit is simply a small piece of code for any single function. So when we test those units, it is called a unit test. The unit test is a short script or piece of code designed to verify the behavior of a particular unit independently to produce a pass or fail result. Unit Testing is performed during the application development phase.

How do I write and run a C++ unit test?

You can write and run your C++ unit tests by using the Test Explorer window. It works just like it does for other languages. For more information about using Test Explorer, see Run unit tests with Test Explorer.

How to define and run tests in Visual C++?

You define and run tests inside one or more test projects. You create the projects in the same solution as the code you want to test. To add a new test project, right-click on the Solution node in Solution Explorer and choose Add > New Project. In the left pane, choose Visual C++ Test. Then, choose one of the project types from the center pane.


1 Answers

Mock getchar:

  1. Utilizing preprocessor, e.g. in your test file.

    #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. Substitute symbol for the linker(harder, in my opinion), e.g. define your own getchar somewhere in your source .c files instead of linking to a stdlib(e.g. msvcrt on windows)

  3. Modify function under test to accept a function returning char, best choice(IMHO) - no conflicts with stdlib. And setup a test by passing a thingy like mock_getchar from point 1 in test code.

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

For points 1 and 2 I'd propose to use your own function instead of getchar (e.g. mygetchar) - this way you could mock/substitute it without facing conflicts with std includes/libs.

like image 190
kerim Avatar answered Oct 09 '22 10:10

kerim