In this article, I would analogize TDD cycles with the process of design by a designer.
Before producing beautiful works, usually, a designer starts by making a sketch first. Why is sketch important? Sketching can provide an outline of the work you want to create and helps discover the best ideas and solutions to a design problem.
Likewise with the tests that we made. Tests can guide us through our code implementation. With the test, we are required to outline our code so that we do not implement the ‘freestyle’ code. This clarifies the purpose such as input and output of our code. Also, the code that is built based on the outline will certainly be more elegant because we implement it simply. This can prevent us from writing unnecessary complex code and keep our code clean.
Creating tests can also help us to estimate possible edge cases. This ensures that the code being implemented has handled edge cases because this is the only way our code can pass the test.
Creating tests can also save time and energy. WHAT? Are you serious? Yes, I am! By testing, we can prevent useless code implementation. Or, in the fashion designer analogy, we don’t need to color the part outside the sketch line.
Typically, the test stages are marked with a [RED] tag.
Coloring: Implementing the code
After finishing making the sketch, now is the time to color the sketch so that it becomes a work. In software development, the process of coloring a sketch is the same as implementing the code based on the tests we have created. Usually, the code implementation phase is marked with a [GREEN] tag.
Code implementation should refer to the tests that have been made. Apart from passing the test, this can help us maintain the KISS principle (Keep It Simple and Straightforward). This can help us to build a clean and single responsibility code.
This stage is optional. Not all designs have to undergo revision. Revisions to designs are generally carried out to beautify a work without changing the purpose for which the work was created. Likewise with our code. Not all code has to undergo refactoring. Refactoring is carried out if there is an implementation that can be improved without changing the behavior of the code itself. Usually, this stage is marked with a [REFACTOR] tag, and the code after the refactor must still pass the test without changing the test.
The only difference between the design step and the TDD cycle is that once you have finished revising the design (if needed), the work is ready to be launched. Meanwhile, in TDD, the Refactoring process is not the end of the story. TDD is cyclic, which means that after refactoring the code there is still a possibility that we will repeat the Testing phase.
Then, what are the advantages of implementing TDD?
TDD implementation can help us to write less complex code. If the current code has passed the tests, we don’t need to add more code. Therefore, TDD can prevent us from writing unnecessary code.
In TDD we are encouraged to write unit testing. Unit tests will test individual units of software. This can guide us to implement modular and single responsibility code.
Tests can help us debug our code when an error occurs. We only need to refer to tests where our code doesn’t pass. It will help us to save our time because we don’t need to do end-to-end debugging of our code.
TDD implementation is not easy. I am still adapting to build applications with TDD. However, after experiencing the benefits, I became more and more excited about implementing TDD.