By Hélio Costa
Some time ago I heard the following statement:
“I believe that unit tests are important; however, I see no need to carry out TDD.”
How is this possible?
Separating things: Unit Tests
Unit tests are meant to guarantee that a certain business rule is executed as it was solicited/described by the software stakeholders. A test should only cover one scenario; which will come out either happy (a happy path), or a failure. Any and all necessary inputs should be introduced with the help of Mocks and/or Stubs, making sure the test is as independent as possible from the rest of the classes that collaborate/interact with that snippet of code in real life (production code).
A way to verify if your tests are well written is to analyse the anatomy of a unit test — there should be: a snippet to input the data necessary to the tests; execution of the code which is being tested; and finally, an analysis of the obtained results.
Performing the test after the production code is ready could initially provide you with some confidence in what you’re doing. However, as the application grows, you’re likely to lose control of your test suite and end up with a bunch of coupled tests that don’t necessarily cover all production code. At this point, you might reach a dead end and unfairly blame “that fallacy of testing software”.
We can also affirm that performing unit tests just to show your boss isn’t a good idea. The kudos you might receive today can easily turn you into a villain when you lose structural control of your code.
Separating things: Test-Driven Development
At its core, TDD is: Red, Green, Refactor. Put simply:
- Write the test in a way that will exercise an isolated part of your code (you can read about this above).
- Write (production) code that will make the test green (pass).
- Verify that your production (or testing) code can be improved; either in writing, quality or a language’s “best practices”.
Repeat this process until you begin to reap the results of TDD. You will get used to this in a matter of a few weeks. Remember: baby steps are important in this phase, and take your time doing this. Don’t write 20 lines of code without using your test to verify what’s going on. There’s no pressure. You’re learning a new way of looking at the world.
One time, looking over some of our code, I found a method that had 37 temporary variables; 7 loops; 11 ifs/else; and 5 comments on one line.
It’s clear that the programmer no longer knew where to put things. He lost control of the code in such an extreme way that he needed to iterate the same Collection 3 times, and each did different things.
There’s no need to get into the details of the Single Responsibility Principle; Don’t Repeat Yourself. He didn’t know where to put each thing, period.
This is where TDD helps. It’s like a guardrail, ready to raise a flag as soon as you start to get lost. It will show you through tests, the necessity of rethinking the solution and reorganizing code for a new feature.
Test-Driven Development is about code, not validation
While you don’t have this vision, you’ll continue to suffer from debugging, duplication to the nth power, and the infamous Yoyo Bug: the resolved bug that keeps reappearing.
The Meeting Point
Unit Tests + Object Oriented Design: Test-Driven Development Design.
No, you’re not a programming ninja. It doesn’t matter if you have a fully developed idea in your head. I bet that if you write your tests first, your initial idea will be just a draft of your final solution guided by tests.
My final tip: be patient. When you start writing unit tests, do it the classic way: Red, Green, Refactor.
Our goal in Product Technology is to create the best solution to our customers’ needs by offering the most complete and innovative portfolio of financial products from financing to investing. We’re here to build a fully automated and intelligent digital platform and we’re looking for people who’ll join us on this link.