Most of my C library code can be compiled with -DTEST
to expose the main()
(and often some auxilliary functions too) in the source file with the implementation. So if I have a set of functions declared in source.h
and defined in source.c
, then source.c
might look like:
#include "source.h"
#include …other headers…
…code defining functions declared in source.h
#ifdef TEST
#include <stdio.h>
int main(void)
{
…test code…
}
#endif /* TEST */
This works when the test suite is small enough to fit in the source file. If the tests get bigger than the code, then I create one or more separate source files containing test code. Each of those files can have its own main()
, or they can be designed to be linked together — whichever seems more convenient.
What's appropriate depends on the size and complexity of the tests. Some functions end up with fixed — hard-wired — tests; some spend time reading data from standard input; others process argument lists if supplied and fall back on some minimal test if there are no arguments. The test code might use a unit test infrastructure or might be more or less ad hoc, again depending on complexity (and antiquity) of the code.