“All code is guilty until proven innocent.” — a mindset behind Test Driven Development
This article is written as a part of individual review criterion of PPL CS UI 2021
“what is a test-driven development? how does it work? why is it even a thing in the first place?” those are the words of a classmate that I knew of at the beginning of my 3rd semester studying for my CS degree. well, it's not like I know the answer at that time, so I just shrugged it off.
I realized that being a programmer in this age of technological development is not really easy. having to keep up with new technologies and what is currently trendy, or else you will be missing out on a lot of stuff. furthermore, the development of techniques that could help us in our development process keep evolving by the day, and one of those techniques or approaches is currently TDD (Test Driven Development). In this post, I will try to explain what is TDD and its implementation on software engineering projects.
What is TDD Anyway?
TDD in general is a design process, a way of designing software components iteratively, by developing one unit at a time. In short, we write test cases before we write code, and making sure all the components behave like the unit tests specified beforehand.
the general rule of TDD is as follows :
- write a failing test for a component or feature
- write code that is just enough to satisfy the requirement for the test to pass
- refactor to improve the quality of the code.
at first glance, it appears as it is not that difficult to implement, isn't it? well, it turns out that the actual process is way more tedious and time-consuming than that. it is due to the fact that every time a new feature wants to be implemented, then you are obligated to first write the test for it beforehand, and then the software is improved to pass the tests that have just been created, and only that. this is sometimes way more burdensome for some developer that is pressed on time to develop their application and cannot afford for the codebase to be expanded as much as 2x or even 4x the base implementation code.
so then, Why should we (not?) do Test-Driven Development.
Why should we do TDD?
to begin, let's understand the importance and value of tests in the code. by writing tests, you really consider and take your time in deciding what you want from the code that you are going to write. you also reduce time on rework and debugging the code due to the test acting as a safety net, allowing you to see what the mistake, where it is, and how it affects the entire program. It helps identify errors in a really short period of time and whether or not you have created the desired functionality of the code, this factor also makes refactoring a piece of cake.
So, How do we implement it in our project?
So, in the current project that we are working on, the normal cycle of TDD is as shown:
- Red: write the test for the desired feature, run it and see it fail.
- Green: implement the feature, but just the base functionality to pass the test
- Refactor: improve code quality, fix mistakes, implement the logic, syntax, and desired function of the feature.
now for the sake of explanation, I will use a requirement from the project to create a breadcrumb hierarchy of the file location in the folder structure.
first, we write the test for the feature itself.
here, we create the test according to the desired functionality from the breadcrumb feature, such as expecting them to be able to handle the input and exist in the webpage.
when we run the test, the pipeline should fail. [RED]
after that, we implement the breadcrumb feature.
in the implementation, we proceed to satisfy the unit test and should be able to get the pipeline to pass [GREEN]
now, although the code is working, we will now clean it up and improve the quality of the code, also adding new implementation and complexity to the feature itself.
refactoring the code won't cause the pipeline to fail again [RED] but instead will just stay passed with the tag [REFACTOR].
after implementing a complete TDD system on my own project, I realize that there are a lot of benefits such as easier error handling and refactoring, stuff that would take me hours if a TDD system was not implemented in the first place.
But the hindrances of TDD also accompany it as expected, writing a function that usually would take me at most 30 minutes, extended into almost a 3-hour sprint of trying to figure out the test implementation and its intricacies, but it is as expected of a test-before-development system anyways.
so overall it's a give-and-take experience for me, but surely the advantage of just being able to know where the error and bug throughout the entire codebase outweigh the negative aspects by a major lot.
and that in itself is worth every damn minute.
Now hopefully, you should know about TDD basics and how it's implemented on a software project. Should you be implementing it yourself in the future, I wish you the best of luck!