Test-Driven Development (TDD) is one of the practices introduced in Xtreme Programming3, a very popular agile methodology. So what exactly is Test-Driven Development? In this blog post, let us understand the process of Test-Driven Development & how it is used in real-world scenarios.
Test-Driven Development is a very popular approach to testing where we write the automated tests first, and then write the code for the functionality/feature. It is a real paradigm shift because of the way software is traditionally tested and delivered, especially if you are coming from a waterfall background, where the software is tested manually after the feature is completely written.
Different Stages of Test-Driven Development:
The entire process of Test-Driven Development is practiced in 3 different stages.
The Developer and the Tester discuss the requirements of a User Story1 at the beginning of an Iteration. The Tester needs to have a complete understanding of the User Story’s Acceptance Criteria2. The Developer & the Tester will discuss the first piece of functionality in the User Story to be implemented. The Tester will write an automated test for that piece, using standard testing frameworks like NUnit or JUnit &, at the same time, the Developer will begin to implement this little piece of the User Story.
Once the Tester writes the code, he runs it, causing it to fail because there are no classes or methods created yet. This is the Red stage. The idea of this stage is to fail fast. Failing fast gives an idea of what is going wrong earlier in the implementation. Failing gives feedback based on which the design can be improved.
This is the stage in which the test is created. The tester needs to visualize the final end product to create tests. He needs to begin with an end in mind. This is where acceptance criteria / Mock-ups / Storyboarding comes in handy. The team grabs the information embedded in these artifacts coupled with their imagination to create tests. Since the methods / Classes they are making use of still doesn’t exist, they will get red squiggles in the code. IntelliSense option is as well, not available. But that’s fine. Still, go ahead and create them.
Once you create the test, add the stub for the method for which test is created. Now, all the red squiggles shall go away. Build the solution. Run the unit test. The test shall fail & it is fine & expected, as we have not added any logic within our code yet.
In the next Green stage, the Developer writes just enough code to pass the test. The intention here is just to pass the test. It could mean that he may take shortcuts to get the test to pass like hardcoding values, or using some dummy methods to return a value, or using any other desperate attempt, but the idea is to get the test to pass as soon as possible.
Two of the principles you need to follow in the Green stage is:
- The KISS principle (Keep It Simple Stupid)
- YAGNI (You Ain’t Gonna Need It)
They mean that do not write any unnecessary code. Just stick to your mission of writing limited code to pass the test. Do not think about irrelevant details like architecture, integration with third-party software, etc. Just pass the test.
Now, remember that the code at this stage is not perfect. The Developer has used shortcuts to pass the test. This is no longer sustainable. Thus the 3rd stage Refractor becomes necessary. In this stage, the Developer refactors the code & replaces the hard-coded values/dummy methods with clear logic. He makes the changes incrementally, and after each change, he runs the tests that were created to make sure that he has not broken down anything. He does this iteratively until the code no longer needs refactoring.
Divide the Refactor stage into many sub-stages. In each such sub stage, have only one goal to accomplish. The various goals in each substage could be:
- Remove hardcoded value
- Improve the design of the software
- Remove duplication
After each time you make a change, run the test that was created during the Red stage. This is to be repeated many times till the code is sufficiently refactored.
One more stage that is commonly associated with the Red-Green-Refactor cycle is the Repeat cycle. It basically means that the 3 cycles need to be repeated several times in an hour. The Red & Green cycles will usually be very fast & the Refactor cycle will take more time as we try to adhere the code to the Acceptance Criteria.
This is the entire essence of Test-Driven Development.
Test-Driven Development after deployment:
So this is how Test-Driven Development is followed in a usual development scenario, but we will try to understand how Test-Driven Development works after the code is deployed. Let’s suppose that a user has found a P0 bug in Production. What is the response by the team to this event? To repro & fix the bug in the dev environment? No! Since the team embraces Test-Driven Development from the ground up, the product is literally driven by tests. Here are the 3 things they do:
- First, they write an automated test that fails, that would test the buggy scenario.
- Then, they write the code to pass the test, & then refactor it.
- And finally, run the entire automated suite to see if the bug fix regresses any part of application & push the fix to Production.
An example to demonstrate the Process of Test-Driven Development:
Suppose that you need to develop a login screen for a Web application. After discussing the requirements with the team (remember this is a prerequisite of Test-Driven Development), the team starts to write tests for the login screen, making sure all the happy & the sad paths are working fine (Red stage). Once the tests are done, the team writes code to develop the login functionality, letting any user to login to the application with the correct credentials (Green stage). The tests are run to make sure the tests are passed after this stage. After this, more constraints/restrictions are introduced into the software. For example, the password should have a minimum of 8 characters, at least 2 special characters, at least 1 alphanumeric character and so on (Refactor stage). These restrictions are introduced one by one at each substage and the tests are run to make sure that nothing is broken in the process.
Then we continually refine the software to make sure the user has the best login experience into our application.
The philosophy behind Test-Driven Development is deeper than you might think. This philosophy, if embraced, may not bring you immediate gains. You may even think that to write tests & then to develop features may take extra time & effort. Yes, it is an extra effort! But that effort is worth it as you may have very fewer maintenance challenges in the long run. In fact, maintenance costs contributed to 65% of the Software development cost. So there is a renewed hope that Test-Driven Development will ease maintenance challenges and significantly reduce the cost of delivering the software in the long run, if not in the short run.
Once you understand the process of Test-Driven Development, check out the benefits of embracing Test-Driven Development in your project.
Would you like a 360° view about Test-driven development? Check out this Pluralsight course with a free trial
1 User Story – In Agile methodology, requirements are captured in the form of User Stories from an end user perspective
2 Acceptance Criteria – The criteria laid down by the customer for the acceptance of the implementation of the User Story.
3 Xtreme Programming – One of the popular Agile Methodologies like Scrum, Kanban, etc
As always, please leave your comments. I’d really appreciate them.
Want to be notified as soon as I post? Subscribe to RSS feed / leave your email address in the subscribe section. Share the article to your social networks with the below links so it can benefit others.