4

Simple question I hope. I have a function that keeps prompting for user input (characters) and returns a character once it finds that the input is valid under certain conditions. I'm writing tests for this and other similar functions, but don't know how to fake user input. By the way, I'm using scanf() to get user input.

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
endmade
  • 159
  • 1
  • 4
  • 9
  • 1
    put stuff into the inputstream? –  Jul 25 '11 at 01:22
  • Possible duplicate of [How to unit test c functions involving IO?](http://stackoverflow.com/questions/14028950/how-to-unit-test-c-functions-involving-io) – Valryne Oct 05 '15 at 21:16

6 Answers6

7

You can change the behaviour of standard input to read from a file with freopen. Place the test input in a file and call this before your test.

freopen("filename", "r", stdin);
Tugrul Ates
  • 9,451
  • 2
  • 33
  • 59
  • That works for me, but why doesn't it work when I try something similar with fputs() or fprintf()? e.g. 'fputs ("string\n", stdin);' – Andy Alt Jul 05 '19 at 08:43
  • 1
    You are trying to write bytes into an input stream, expecting it to behave like a stack. This will work for files opened for both reading and writing modes enabled, but not for `stdin` as initialized for your process. – Tugrul Ates Jul 05 '19 at 20:25
3

You can do something like

echo -e "Test string\nAnother string" | ./a.out

The string of echo command should be in the sequence which the program requires

cat test_str_file | ./a.out

The file test_str_file should contain the test strings in the sequence the program requires

On the other hand you can simply replace the code's input section with some dummy sections. If you have a separate module for input, then replace it with dummy.

phoxis
  • 60,131
  • 14
  • 81
  • 117
1

If you're on unix or cygwin, you can invoke your executable and ask it to use a text file as stdin. For example:

bash$ ./a.out < input_file
jman
  • 11,334
  • 5
  • 39
  • 61
0

Move the validation to another function. And test it independently. Or fake the user input refactor the remainder to take in a function pointer that is called back to collect some letters. That should enable a simple fake.

I've not written C for a long time but something like could also work

/* test this independentaly */
int isvalid(char* chars){ 
  /* do stuff and return result */
}

/*real function */
char* getinput() {
  scanf(....)
  return stuff_from_scanf;
}



/*fake/mock function */
char* getinputFake(char * testString) {
   return testString;
}


test() {
 int result = isvalue(getinputFake("test data"));
 /* rest of test */
}

You don't need to test the scanf function, but you could replace it with a fscanf and pass in the stream with the chars like this

stdin

char* getinput(FILE * stream) {
   fscanf(stream....)
   return stuff_from_fscanf;
}


test() {
 FILE * stream = .....; /*create a dummy stream say from */
 int result = isvalue(getinput(stream);
 /* rest of test */
}
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
0

Why not just call the function with a default value?

pradeek
  • 21,445
  • 2
  • 31
  • 32
0

This is a very naive solution, but it may do what you want:

char getFakeUserInput()
{
    static char* fakeInput = "This is some user input\n";
    static int pos = 0;

    if(pos >= strlen(fakeInput))
        return '\0';

    return fakeInput[pos++]
}
Chris Eberle
  • 47,994
  • 12
  • 82
  • 119