Continuous Engineering - Test Driven Development (TDD)

as anyone ever asked you one of the following questions?

1)      How do we move quality left / have fewer defects?
2)      How can we move faster / optimize our processes?
3)      Where is your unit test plan and what were the results?
 
The answer is probably “yes”, especially if you’re an engineer. I’ve performed both engineering and non-engineering roles in my IT career, so I know how it feels to be on both sides of the coin – as a Project Manager or Analyst, I often found myself asking the question, “Did my engineer even test this?” And as an engineer, I found myself saying, “It doesn’t matter how much testing I do, or how much documentation I write, I always miss something!”
 
But there are ways to improve the engineering world of unit test – one of them is Test Driven Development (TDD).
 
Benefits
Before I dive into the details of how TDD works, here’s a sales pitch. Why should anyone care about TDD? If done properly, TDD can positively influence many metrics we care about:
1)      Increased Quality
2)      Decreased Time to Market
3)      Decreased cost of ownership
4)      Balancing technical debt with refactoring
 
My first assignment here at The ERIE was to dynamically generate an e-mail detailing specific changes to commercial policies out of our C-LION system. One of my personal goals was to explore TDD and test automation, and gather detailed data around what value it delivered – measured in real hours of effort and number of defects.
 
Here were the stats on defects (combined across our assembly testing and the QA Test Pass 1):
1)      Requirements Coverage: This piece of code was responsible for fulfilling 14% of the requirements on the project
2)      Defect Generation: This piece of code was responsible for 4% of the defects. Of these, all were identified during assembly testing, and none were found during QA Test Pass 1. A side benefit was that the quality of the code was so high, that QA was able to reduce their planned scripts in Pass 2 by 20 scripts! That’s moving quality left.
 
From a cost perspective, I originally estimated that I would write 158 Tests at an estimated 90 minutes of coding time per test (that’s 237 hours of effort). My actual effort was 339 Tests at 15 minutes per test (85 hours of effort).
 
Conclusion: TDD is faster to do than I expected and delivers higher quality than other pieces of code that did not utilize TDD. As a side benefit, the tests were repeatable, providing a good safety net for refactoring and enhancements in the future.
 
Are you sold yet? I was.
 
Process & Methodology
The TDD process is deceptively simple. Here’s an outline of the process (pulled from Wikipedia):
·         Write a test case
·         Confirm new test is failing
·         Write “minimal” code to pass the test
·         Confirm new test is passing
·         Refactor code
·         Rerun all tests and confirm passing
·         Repeat!
 
At first, it seems silly to write a failing test case FIRST. I remember thinking, “Of course it’s going to fail; the code’s not written yet!” But the value isn’t actually in writing a failing test first – instead, it’s about designing code that is, in fact, easily testable. This can be a difficult mindset shift for engineers (it was for me!), especially when unit tests can sometimes be an afterthought in our Tech Designs.
 
What I learned was that I could more easily identify flaws that I had not anticipated in my design. I also was able to quickly refactor code when I needed to and confirm that the code was still giving me the expected output. Lastly, I had immediate feedback on most defects that I accidentally introduced into the code. It wasn’t fool-proof, but it definitely helped. The increased quality and time reductions were just a natural consequence of the process.
 
There were a few drawbacks. First, the code tended to became more modular, which increased potential for reuse but also increased complexity. Second, the mindset shift produced by TDD was so drastic that it was difficult to explain why I had written the code in a particular way – it had to be testable, and that impacted the design. Finally, it was easy to get carried away with testing every possible combination of use case; a balance needed to be found between test coverage and the risk/impact of potential defects.
 
Available Frameworks & Tools
There is a plethora of TDD tools available today for use. Often times the tool has to vary for the technology you’re working with (JUnit for Java, Cucumber for UI, etc), or you can build your own framework when one isn’t readily available.
 
If you’re interested in learning more about TDD, a quick search on the internet is all you need. For hands-on experience, talk to your Tech Lead or SLE about shadowing another team that’s doing TDD today to see how it’s done, or talk to your supervisor about attending some training. The investment is small, and the potential payout is high.
 
I hope TDD can give you some of the answers to those tough questions about quality and speed. Happy testing!
 
I want to thank Tim Weindorf for taking the time to author this post. If anyone in the organization would like to follow in his footsteps just contact me and we'll discuss making that happen.
 
Next time we will discuss design and automation all the way to Production.