Unit Testing in Embedded System?

    This was an unusual topic to me at first while I have worked as firmware engineer for microcontrollers. Most of microctonroller applications are still developed in C or C++.  In the past, while you developed something in C, you barely heard about unit testing. You needed to research a long time to set up a unit testing environment. At this moment, the most popular one might be Unity or CPPUtest, but they are not easy to use when the code has complex dependency upon each other because you need to create mock objects to your own manually. The importance of unit testing has been popular recently with newer high level languages such as Java and C#. Those languages have standard unit testing framework. Java has JUnit and Visual Studio provides a unit testing framework for C#. Unfortunately, C was developed before the rising popularity of unit testing and it did not come up with standard unit testing framework.

    From my personal experience, unit testing was introduced to me while developing functional safety products. To comply with functional safety, unit testing has to be done for the production code. This is a way to prove if the production code meets software unit's requirements & design. Since then, I have needed to do unit testing production code and research about unit testing framework. Luckily, there is new unit testing framework for C called Ceedling (http://www.throwtheswitch.org/ceedling). It is combined with Unity, CMock and CException. It resolves the worry of spending too much time to create mock functions on Unity or CPPUtest when it can be done faster. Ceedling can automatically generate mock functions for me and I do not need to write it manually.

    Writing software in embedded system is unique in that the software directly interacts with the hardware. For example, one of the software specifications is "Software shall be able to turn on an LED". Is this enough information to write unit test specification? No, because we do not know that turning on an LED means whether logic 1 or logic 0 on microcontroller's pin that is connected to an LED. This should be also part of software specification derived from hardware constraints. For example, "an LED shall be active-low". This means that when the microcontroller sets logic 0, an LED will turn on. Assume production code has a function named "turn_on_LED". This functionality can be tested by making a test code in Ceedling that will call the "turn_on_ LED" function and place assertion function next line to verify if the microcontroller's pin logic is 0.

void test_turn_on_LED(void)

{

    turn_on_LED();

    TEST_ASSERT_EQUAL(0, read_LED_PIN());

}

    I believe that many firmware engineers think there is not much work to do without target hardware. I was one of them, too. With unit testing, I show how to verify "turn on an LED" without hardware. This is the way unit testing works in embedded system. You will do the same test with hardware later. But at that time, if an LED does not work as expected, the issue can be addressed in hardware or specification not software. Next time, I will introduce Ceedling.