Jul 14, 2012

Test Driven Development for Embedded C: Introducing runtime-bounded test doubles and the mock object

I had a meeting with reading group of "Test Driven Development for Embedded C" in Tokyo, Japan. We read the chapter 9 "Runtime-Bounded Test Doubles" and the chapter 10 "The Mock Object", then we discussed them. In this entry, I introduce the chapters and some topics from our discussion.

The chapter 9 "Runtime-Bounded Test Doubles"

When we implement product code with C, we have three ways to replace dependent module with test doubles. They are preprocessor substitution, link substitution and function pointer substitution.

Link-time substitution, which is introduced in chapter 7 "Introducing Test Doubles", is not flexible because it can't be replaced at runtime. If you want to use product code once and use test doubles at other time, function pointer substitution, which is introduced at chapter 9, is effective way.

Although function pointer substitution is very flexible, it has a side effect. Heavy usage of preprocessor or function pointer substitution reduces code readability. You should use them in a limited way.

By the way, the author doesn't explain preprocessor substitution. He may doesn't like it because of side effect.

The chapter 10 "The Mock Object"

The chapter 10 introduces the mock object, which is not so popular among embedded software engineers. The subject is a device driver for existent flash memory. The mock object is useful way to ensure quality of device driver before integrate it with hardware because:

  • It is difficult to test complex interaction between software and hardware based on specific protocol with usual testing framework.
  • It may be impossible to test error case in real device. 

Most part of the chapter 10 focuses on how to implement the mock object in C. You can also know "CppUMock", which is C++ mocking library, and "CMock", which is mock generation tool for C.

I found that mock object is usually complicated. If you implement mock object in C by yourself, you must to test it thoroughly before you use it. Test may be unnecessary if a mocking library assure quality of mock object.

You might think that making mock object is waste of time. But I think that it worth spending cost to make mock object and test with mock object. The more you standardize  device I/O, the more effectiveness of test grow. You can ensure quality of device driver more and more before integrate it with hardware.

At last we discussed why the mock object is popular among enterprise or web engineers but not among embedded engineers. Our conclusion is that mocking library with LL is very useful because LL has less constraint and mocking library is well maintained to use easily. On the other hand, library for C/C++ are still on the way to become useful.

This is one of difficulties for embedded engineers. To gain strength from TDD, we need to prepare way to overcome language constraint.