In my last blog I waxed poetic about C. It was heart-felt, but it was also a little bit embarrassing. I do love the language but it does have its share of trouble.
The problem that I run into most often in C is testability, particularly unit-testability. In theory, there should be no problem. It's easy to test simple functions in C. You just call them from a test harness and away you go. The "not so simple functions" are the ones that cause trouble.
In a procedural language, there are at least two types of functions: leaves and branches. Leaves sort of "bottom out"; they don't call anything else other than library functions, and they are relatively easy to test as long as they don't have side effects outside the system. Branches are tougher: they call leaves and other branches. If you test a few branches up from the leaves, you are not really unit testing any more - you're component testing. And, if those leaf functions touch a database or argue across a socket, you're probably system testing through your unit tests, whether you want to be or not.
So, how can we handle this? How can we easily unit test a branch function without going all the way down the call graph?
The nice thing about C is that it presents you with options. You can play clever tricks with the processor and #define various lower level calls, but it's ugly.
Another option that comes up is the link seam. If you have functions that you want to replace you can place them in another library. When you are testing, you can link to a library of stubs. When you are building your production code, you link in the real library. This approach can work, but it leads to a lot of complication. You can only stub functions that you place in a different compilation unit and your makefiles become a mess.
Fortunately, C has a third way of breaking dependencies: function pointers. Let's look at a radically simplified example.
void process_message(struct message *in)
{
struct message out;
encode(in->header, strlen(in->header), out.header);
encode(in->payload, strlen(in->payload), out.payload);
send_message(&out);
}
Can we stub out the send_message function?
How about this? We can introduce a stuct that holds a pointer to the send_message function and an instance of that struct type:
typedef struct {
void (*send_message)(struct message *in);
} message_port_type;
extern message_port_type message_port;
Then, we can change our call to this:
void process_message(struct message *in)
{
struct message out;
encode(out.header, in->header, strlen(in->header));
encode(out.payload, in->payload, strlen(in->payload));
message_port.send_message(&out);
}
All we have to do now is make sure that we initialize the function pointers at startup. If we need to mock those functions, we can set the function pointers to the appropriate mocks prior to each test case.
It looks suspiciously like C++, doesn't it?
I often show this style to C teams, and most of the time, they regard it with suspicion initially. Some (but not all) C programmers regard OO as hype; they think that it muddies the design. But, the testing problem is real, and this technique can help. It's a thin layer of objectness that makes unit testing manageable.

Comments (9)
Maybe if C was in the limelight these days you would have tools to do unit testing.
This brings to mind some tools I used to learn C with. Lattice C compiler and the command line options, what a pain but I learned the hard way.
Then the interpretive C crowd. 2 software packages I used were C-Terp and Instant-C.
Instant-C was a standout for me as it allowed one to test functions without having to write main() or a whole process behind it. Ah the glory days :-)
Posted by David Camacho | January 30, 2008 6:32 PM
The key issue for testing is substitutability, as you point out. I once tried TDD with bash scripts (yeah, well it was raining that day) and actually made some progress. The only way to get around trashing the file system with each test was to use environment variables to substitute commands. The result was a collection of short, coherent scripts that called each other that looked much more tractable than the usual stream-of-consciousness we all usually write. An interesting experiment.
One more thing with C, the other thing to consider for testing is the use of scripting languages, all of which have good C extension hooks. Then it'll turn out you can lash together all sorts of interesting stuff.
Posted by Steve Freeman | January 31, 2008 5:41 AM
Check out ATF from netbsd. It's new, but promising.
http://www.netbsd.org/~jmmv/atf/
Posted by matthew sporleder | January 31, 2008 12:43 PM
For more details of how to work with code in C you can read the pretty nice book: Working Effectively with Legacy Code (Robert C. Martin Series).I use CppUnit Lite for unit test. The only thing that i hate is to mock all Windows calls , and have a good coverage.
Posted by Felix | February 1, 2008 6:58 AM
Sometime back I've used Parasoft's C++Test which does "Automated generation and execution of unit and component-level tests with flexible stub framework":
http://www.parasoft.com/jsp/products/home.jsp?product=CppTest
Posted by c4swimmers_net | February 4, 2008 11:08 PM
What's the advantage of using a struct instead of a global function pointer?
My C is a bit rusty. Is there anything in the language that would prevent or make the following suboptimal:
typedef void (*send_message_t)(struct message *in);
extern send_message_t send_message;
...
send_message(&out);
...
?
Posted by Marius Gedminas | February 5, 2008 12:01 PM
Marius: Hi. Grouping is the primary advantage. I figure that if you are going to go to function pointers you might as well have something that seems like a namespace. You're right, though. It's not strictly necessary.
Posted by Michael Feathers | February 5, 2008 1:40 PM
As funny as this may sound, I prototype a unfamiliar systems out in PHP before I make a C version. Most of the problems I run into are unexpected undefined behaviors, especially when I'm writing something network-oriented (and what ISN'T these days?).
PHP allows me to rapidly prototype things which aids in identification of problem areas, and makes it quicker to experiment with work-arounds. Once I'm satisfied with my PHP design, I convert it to C if I feel there is anything substantial gained by doing so.
I have a basic C library of functions I wrote that mimics alot of the common PHP functions (which themselves are usually very similar to libc functions alot of times).
Using that, I can typically convert a ~2000 line script in less than half an hour since the languages are syntactically similar, and the main thing I'm left to account for are the variable types.
Of course, less than 1% of my programming experience has been on windows. I would expect my process to not be nearly as neat and clean on win32, since none of my prior dealings with those OSes have been.
The branch versus leaf thing still applies I suppose, but that's just the nature of the beast. For me, PHP makes the process quite a bit quicker, which is about the best I would expect.
Posted by Jack Gierra | February 6, 2008 3:15 PM
Marius Gedminas is right in his comment, if you don't like the C++ like syntax, you can just declare a function pointer directly for send_message(), omitting the structure, and you don't even have to have a typedef:
/* Prototype */
void messagesender(struct message *in);
/* Wrapper variable */
void (*send_message)(struct message *in) = messagesender;
This then looks exactly like C when writing the code to call send_message(), and allows runtime or compile time switching like the structure example.
Posted by Michael McTernan | February 12, 2008 12:24 PM