You can do this, by wrapping your function and redirecting output to some stream other than stdout
. I will slightly change the example, but the main idea is the same. Suppose we have the following function:
void even(const int number)
{
if(number % 2 == 0){
printf("%d is an even number", number);
} else{
printf("%d is an odd number", number);
}
}
Now we will change this to print into any stream and wrap it to keep normal performance for a user (even turn it into a static function, so the user of you library has no idea of the wrapping):
void _even(const int number, FILE* stream)
{
if(number % 2 == 0){
fprintf(stream, "%d is an even number", number);
} else{
fprintf(stream, "%d is an odd number", number);
}
}
void even(const int number)
{
_even(number, stdout);
}
To test _even
, we can create a temporary file, redirect output of _even
into it, and then check if it matches our prediction.
int test_even(const int input, const char* output)
{
FILE* tmp = tmpfile();
const int length = strlen(output) + 1;
char buffer[length];
_even(input, tmp); // Redirecting
const int tmp_length = ftell(tmp) + 1; // how many characters are in tmp
rewind(tmp);
fgets(buffer, length, tmp); // Reading from tmp
fclose(tmp);
if(strcmp(buffer, output) == 0 && tmp_length == length){
// Test succeded
// Do what you want in here
} else{
// Test failed
}
}
What exactly you should do when your test succeeds or fails is up to you, and up to how you design your unit testing. And you can then run it like this:
test_even(17, "17 is an odd number"); // succeeds
test_even(0, "0 is an even number"); // succeeds
test_even(-1, "-1 is an even number"); // fails