Test-Driven Development for Embedded C is an excellent book by James W. Grenning. The is a book not only about the what of embedded test-driven development, buy also the why. Starting from the very basics of unit testing C code, it goes through the whole skillset required to test embedded software.
The book begins with forwards by Jack Ganssle (perhaps the highest regarded spokesman in the embedded software community) and Robert Martin, one of the fathers of the agile software movement.
The book is split into three main sections:
- Getting Started.
- Testing Modules with Collaborators.
- Design and Continuous Improvement.
In this first section a device driver is developed from scratch using test-driven principles.
One tip I really liked in this section was the idea to make a list of all the tests that you would like to perform before you start. It seems obvious now, but I’ve never done this before. This list will change as go along with the development but it can help crystallize the requirements in your head and expose a good strategy for progression.
The discussion on embedded TDD strategy was interesting. Covering the target hardware bottleneck, the benefits and risks of dual-targeting, and the embedded TDD microcycle, it focused on issues that are unique to those of us in the embedded world.
The author’s past experience from teaching TDD to embedded engineers seems to come through in the “Yeah but..” chapter. Here he gives answers to the different objections that are often raised to using the TDD approach for embedded software. I liked this because focusing on techniques without examining the underlying motivations can make for disastrous teaching experience.
Testing Modules with Collaborators
In the previous section the tests were all written in C using the Unity test framework, but from here on in all the tests are written in C++. At first it might seem counter-intuitive to write tests for C code using C++, but the reduction in required boilerplate code is immense. This mirrors my experience and is how I test C code.
This section goes beyond the basics to show how testing is done in large projects. Techniques for testing cross-module interactions, the breaking of dependencies, and the use of test spies and mock objects are covered. The 0-1-N pattern for testing collections classes is such a universal approach I’m glad it was explained.
The section finishes with an worked example using mock objects to develop a flash driver with complex hardware interactions. This is about as hard as it gets with embedded software, and it is refreshing to see a book that tackles the hairier problems in example code.
Incidentally, if you are looking for a lightweight, header-file only fake function framework I know a github repo made just for you.
Design and Continuous Improvement
The third section begins with an illuminating discussion of SOLID principles in connection with procedural code. An earlier example is reworked using the SOLID principles to improve the design and the tests. It is a nice reminder that good design is good design, even outside of the object oriented world. This flows into a chapter looking at refactoring, where code smells are identified and addressed in the context of a passing test suite.
There are also chapters on adding tests to legacy code, and test patterns and anti-patterns.
This is a book that we in the embedded software community have urgently been in need of. It forms a body of knowledge that up until now has been hard won by individuals and teams but not spread into the common knowledge of the community as a whole. If you are an embedded software engineer you have to buy and read this book.
It is not complete or perfect, but it is close. This book is an great place to start with TDD for experienced embedded software engineers and stands alone as a tutorial in this respect. I would have liked an additional chapter on acceptance tests and hardware in the loop testing, but I suppose you have to draw the line somewhere. The book references Refactoring and Working Effectively with Legacy Code throughout, both excellent books that would make good companions to this title going forward.
 As the book is still in beta you should take this review with a pinch of salt.