Test-Driven Development
Foreword
Much of the content written in this guide is referenced from the book, "Test-Driven Development for Embedded C" by James W. Grenning. The explanations and input provided by him through the book do a great job of introducing the concept and gradually progressing to how the techniques can be used in a more advanced way such as virtualizing/faking drivers. With that said, many of the items mentioned from this section is referenced from this book.
TL;DR: If you at all care about software quality assurance particularly for embedded, this is an easy recommended read!
Introduction to TDD
We've thrown this term around quite a bit but let's it's time to start disecting this paradigm. As the name suggests, Test-Driven-Development (TDD) is a design scheme that encourages the developer to let the tests drive the progress of development. In a sense, TDD is designed to control the rate and direction of development such that each feature added is required (i.e. has a requirement), the implementation is tested and validated, and with each change or modification, the system as a whole is not compromised.
Why Should we Practice TDD
Much like with many of the other techniques, we need to analyze the benefits of why this technique should be practiced or integrated into our workflows. To answer that, we should look at how many developers choose to test their code.
A Bad Habit of Developers
A common trait amongst developers at any level is practicing the "fix it later" or "build it and then fit it" mentality. Effectively, this approach to development involves writing all source code first and only after completing development, (partially) testing the code/firmware that was written. For small project and prototypes this can certaintly be acceptable.
However, for larger and more complex projects, practicing this development style only opens up potential issues later in the project life cycle. Namely, there is the likelihood of the system not functioning as expected. At a surface-level, you will almost certainly run into a lot of compilation issues.
Note
Remeber that software bugs become more expensive to fix the longer that you leave them unresolved!
The takeaway is that your feedback or the point when you will realize the system is malfunction (or not functioning at all) is delayed. By association, because you find the issues later, the time it takes to fix the issue only increases as well.
Benefits of TDD:
TDD is a remedy to the issue presented above. It is much more responsive to changes made during a projects lifetime and ensuring correctness throughout development. You do not have to wait until the end of a sprint or major feature implementation to start testing and finding issues.
Similar, we can observe the following benefits from using TDD:
- Fewer bugs
- Shorter debug time
- More reliable documentation
- Reduced risk and greater confidence
- Improved software design
- Ability to test code before having hardware
- Introduces simulations
- Encourages portable code
How does TDD work
Test Driven Development can be summarized down into a five step process:
- Add a small (atomic) test
- Run all tests and see the new test case fail immediately (Might not compile even)
- Make changes to the new test case in order for it to pass
- Run all existing test cases and ensure that all pass
- Refactor code base and then re-run all test cases
Note
Don't forget to write your software/system requirements :)
The next exercise will walk through a slightly modified version of the TDD process from start to finish. That said, there are still a few more things to talk about in regards to TDD.