When replacing production C code with test doubles (or fakes), there are three basic approaches: function pointers, preprocessor hash defines, and link time-time substitution. All three are examples of what Michael Feathers calls a seam, or a way to change the behavior of a program without editing in that place. We use seams when we unit test software to decouple and localise the software under test. Each of these types of seams has different trade-offs for testing embedded C. Here’s what I think.
Function Pointers (run-time substitution)
- + Easy to substitute at runtime for test functions
- + Makes for more decoupled design
- - Harder for IDE to jump to definitions, etc.
- - Can make static code analysis mot work so well
Preprocessor hash defines (preprocessor-time substitution)
- + Good for getting legacy code under test
- - Needs discipline to structure the hash defines well
- - Can make code harder to read and understand
- - Definitions can be hard to locate because they can be set on the command line (-D), include path, header files, etc and can be overridden at any location
Link different function implementations (link-time substitution)
- + Good for getting legacy C under test (limited changes needed to production code)
- - Need to check the link definitions to understand what is running for any given executable
- - Can’t have multiple implementations of a function in one executable
- - Can create the need for multiple test executables
You can use the fake function framework to generate the fake functions for testing, whatever type of seam you choose. It just creates a function and the supporting structure to capture arguments and provide return values. You can find more information about the fake function framework here:
https://github.com/meekrosoft/fff#readme
Image may be NSFW.
Clik here to view.

Clik here to view.
