Test Driven Development Is Useless, Really?

Jonathan Chandra
6 min readApr 4, 2021
Photo by Andrey Zvyagintsev on Unsplash

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.

Example of navbar component

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.

Test Driven Development 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.

Example of Header component

In red phase, I created tests (either unit test and functional test) for the header component. Here is the tests.

One of the unit test for Header component

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 for Header component

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.

Code snippet of Header component implementation code

After that, I checked if all tests is passed like this.

Run tests after write the implementation code

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.

Code coverage example

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.

Code snippet of Header component implementation code after refactor

Then I checked again are all tests is passed or not after refactoring the code.

Run tests after refactoring the implementation 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.

  1. 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.
  2. 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.
  3. 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

--

--