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.