Test Driven Development Is Useless, Really?
This article is made for the Software Project course assignment, Faculty of Computer Science, Universitas Indonesia
When developing a software, you must have heard about Test Driven Development (TDD), what is it?
Before we talk about TDD, we must understand about the test first.
Test
Test in software development means create a code that check if our implementation code is giving an expected output with a certain input. There are two kind of tests, unit test and functional test.
Unit Test
Unit test is a test that test an individual unit or module in our code. We use unit test so we can make a robust code with minimal cost. For example, we want to make a navbar component like this.
Then our unit test can be a test that confirm our navbar component must only have 3 menu on the right side (Threads, Profile, and Logout) and 1 logo on the left side.
Functional Test
Functional test is a test that check a slice of functionality in the system. Functional test help us to confirm that the functionality of the system is working as we expect. For example, with navbar component example in above, we can make a test that check if we click Profile menu on the navbar, it will move the user to a certain url or not.
Code Coverage
When we talk about test, we also definitely talk about code coverage. Code coverage is a measurement of how much our lines of code is tested. The best practice of creating a test is to have 100% code coverage (minimum requirement) which means every lines of our code is tested.
Now we understand about the Test, then what is Test Driven Development?
Test Driven Development
Test Driven Development (TDD) is a software development process where we always create a test first before we write an implementation code. In TDD, there is a cycle that consist of three phases called TDD cycle.
Here is a brief explanation about the phases:
- Red, we start from here. Before we create an implementation code for a requirement of our software that we develop, we create tests first. Red means when we run the tests, it will failed because there are no implementation code that pass the tests.
- Green. After we create tests, we start to create the simplest implementation code based on what the tests expect. Green means that when we run the tests, all tests will passed because we have write the implementation code.
- Refactor. After we create the code that passed the tests, we may fix or refactor our code if we think the code is still not clean without change it’s functionality so it will still pass the tests and green. After we done, if we want to implement another requirements, we start again from red phase and run the cycle.
Example of TDD
Here is example of TDD implementation that I did for my project in software development course. I create tests for React component using jest and enzyme. Now I want to create this Header component for universal use in many pages.
In red phase, I created tests (either unit test and functional test) for the header component. Here is the tests.
Unit test in above is to confirm that my Header will have ‘iAksesoris’ text, back button, and edit button if I pass a certain props.
Functional test in above is to confirm that if user click the back button on the header, user will be moved to the previous page they were in.
When I run the tests, the tests will failed like this.
Then, I push the test to my repository on gitlab with adding [RED] tag in my commit message like this.
Moving to the next phase, green phase where I start to write an implementation code for Header component. Here is the implementation code for Header component.
After that, I checked if all tests is passed like this.
Finally it’s green! Next I push the code to repository again with adding [GREEN] tag in my commit message like this.
Let’s check the code coverage for Header component.
Wow the code coverage for Header component is 100%, is’nt it awesome?
Moving to the last phase, refactor phase, I want to add Proptypes for every props that is needed for this component so other member of my team will know what type of data that should be passed in the props if they want to use this component. Adding Proptypes does not change the functionality of Header component. Here is the Proptypes that I added.
Then I checked again are all tests is passed or not after refactoring the code.
See it’s still green! It means that refactor will not change the functionality of the component, if it changes the functionality, the tests will be failed when we run it.
And then I push the code with [REFACTOR] tag in my commit message like this.
Benefits of TDD
It sounds like implementing TDD is too troublesome. We can just write the implementation code immediately without create many test that gonna waste our time right? Well, here is some benefit of implementing TDD that I already feel.
- Better program design and higher code quality
When we implement TDD, every time before we write our implementation code, we create test that handle some cases that cause error so our code will have higher quality because our code is avoided from failure or error. TDD principle makes us to make a simple code that satisfy our requirement through the tests so our code will have clear structure, straightforward, and brief. Also, we will implement DRY (Don’t Repeat Yourself) principle because on refactor phase, we delete some of duplicate code if there any. - Consume less time when debugging
With our tests, it will help us to notice which part of our code that has a bug by looking which test that failed. Because of that, it will take less time to debugging rather than we search manually if we don’t implement TDD. - Avoid unnecessary code
While implementing TDD, our code tend to only fulfill the test requirements so our code will be concise and easy to understand. We can avoid adding unnecessary code that actually don’t needed for the implementation.
Conclusion
Well now we understand what is TDD and it’s benefits so we can tell that TDD is not useless, it is actually help us, makes our life easier :). I hope this article helps you to understand about TDD in general and makes you to start implement TDD for you software development process.
References
- The Differences Between Unit Testing, Integration Testing And Functional Testing
- Unit Testing vs Functional Testing: A Detailed Comparison
- Test Driven Development: what it is, and what it is not.
- Benefits of Test-Driven Development
- Why Use Test Driven Development: 6 Benefits for Your Project
- Everything you need to know about code coverage