For my first blog post with Atomic Embedded, I wanted to muse about what test driven development (TDD ) is, as I see it, and what all the fuss is about. I’m going to present a few cases for the usefulness of TDD based on my own experience in industry. Hopefully some of the battle hardened embedded gurus out there will identify with some of these scenarios, and see how testing first isn’t really as crazy as it first seems.
First of all, testing should be automated so that there is a short cycle between writing code and seeing if it worked. The importance of automated testing is clear when you look at a project from a long-term perspective. Consider a time when there was a last-minute bug discovery and fix or a requirements change, and you wanted to test everything again but couldn’t because the release is due tomorrow. If this sounds familiar, then you either had to release code that you weren’t sure about or delay the release. Neither of these scenarios are acceptable. Automating tests requires a time investment in the beginning of a product cycle when deadlines are over the horizon. The returns on that time investment come late in the product cycle when deadlines are looming and the stakes are higher.
Now, I understand that automatically testing embedded software has its own special challenges compared to PC application testing. Manually testing embedded software is also painstaking. The reward for automating tests is then greater when compared to PC application testing. So, the argument that automating tests is too hard is nullified because the investment is great, but the rewards are also great.
Believe me, once you see your tests running themselves, it will be like going from crawling to flying, and tools like Unity and Cmock can help get you there.
Re-evaluating the Development Process
Once testing is taken care of, you can re-evaluate your development process. Normally you would write code and then test it, but if testing is so fast now, why make it wait until you’re done implementing a feature? A feature doesn’t really exist until it has been tested. Both testing and coding will have to be done, but if you write the test first boundless miracles await. Allow me to list just a few:
- Asking the right questions: When you first think about how you’re going to test something, it brings up more fundamental questions about what a feature should do and how it should work. You’re probably already doing this sort of thing except you call it designing.
- What if your detailed design could also be your tests? What is more clear to understand without error, a test written in a programming language or the English language?
- Pulling requirements to the beginning of a project: Any ambiguities lurking in your requirements will be flushed out when you start writing test cases.
- Reinforcing feature driven design: You want to see tests passing. It feels good. Testing first encourages you to implement only the features you need now, not all of the stuff you won’t be using anyway.
- Bugs don’t creep into your code: So long as you are thorough with your tests, bugs will be less likely to creep into your project as you and others add features.
At the most basic level, TDD is simply writing and executing tests of your device before actually implementing the feature. This is the main idea of TDD, but it’s not the only one. Learn more about TDD and XP in Extreme Programming Explained.