In my
previous blog entry on the 2-phase unit-testing idea the code sketch looked like this:
/* test.h */
#define TEST(name) if (run_phase(suite, name))
...
/* wibble_tests.c */
#include "test.h"
#include "wibble.h"
...
static void wibble_tests(test_suite * suite)
{
...
TEST("fprintf failure inside wibble")
{
int expected = 42;
int actual = wibble(4, 2);
/* assert expected == actual */
}
...
}
A follow on idea from this to make the string literal test names globally available. Suppose the wibble function looks like this:
/* wibble.c */
#include "wibble.h"
#include <stdio.h>
int wibble(int lhs, int rhs)
{
...
ret = fprintf(stdout, "%d,%d", lhs, rhs);
if (ret < 0)
...
}
And you want to mock fprintf.
You can move the definition of wibble() into its own .func file like so:
/* wibble.c */
#include "wibble.h"
#include <stdio.h>
#include "wibble.func"
/* wibble.func */
int wibble(int lhs, int rhs)
{
...
ret = fprintf(stdout, "%d,%d", lhs, rhs);
if (ret < 0)
...
}
This allows you to isolate wibble() by #including the wibble.func file.
This is quite brutal but it shouldn't affect the behaviour and brutality can be appropriate when your trying to write characterisation tests because you don't have any tests yet.
The last step is to make run_phase() access the suite parameter itself (rather than being passed it) so the TEST macro can be used anywhere:
/* test.h */
#define TEST(name) if (run_phase(name))
...
/* wibble_tests.c */
#include "test.h"
typedef int mock_file;
static mock_file * stdout = 0;
static int fprintf(mock_file * mf, const char * format, ...)
{
TEST("fprintf failure inside wibble")
{
return -2;
}
...
}
#include "wibble.func"
static void wibble_tests(void)
{
...
TEST("fprintf failure inside wibble")
{
int expected = 42;
int actual = wibble(4, 2);
/* assert expected == actual */
}
...
}