Test-Driven Development is a style of development where you write a test for your code first and then write the code to make the test pass.
Many programmers do this in reverse. First, they build the feature and then write tests to confirm it’s working.
There are three phases to test-driven development. Red, Green, and Refactor.
Write a test and make it fail. This is the first thing you do when using TDD to build any feature in your code.
Make the test pass. Your code doesn’t need to be clean or optimized. It just needs to pass. Thus, you remove the obligation to write quality code during this phase and take the quickest step to make the test pass.
In this step, you will take your code sins from the Green phase, admit them, and atone. Now that you have a solution, you understand the problem better and improve your existing solution. You also have a test to make sure you don’t break anything as you refactor.
Decide your requirements and test cases
TDD is great because you focus on the acceptance criteria for your feature. You must decide what you’re trying to accomplish before you start writing code. It keeps you disciplined and focused on a singular goal. In addition, It forces you to consider edge case tests and reveals a feature's hidden complexity.
Create the happy path test first
The happy path is the common path of your feature when everything goes right.
For example, you have an app that lists books. You call a method get_books and it returns all books that were created by the create_book method. So you create one book, and then you find that one book. You do the same for a list of books.
A good happy path test covers the requirements for your feature without being overly specific about implementation details. Keep your test as agnostic to implementation details as possible and focus on your desired behavior.
Handle the edge cases
What about when things go wrong? for example, what happens when you call get_books and there are no books? Do you want to return an empty list of books? Do you want to throw an error? What if there are thousands of books? Is your code performant enough to handle that? Once you’re certain the core functionality works, you want to handle these sorts of edge cases.
Refactor your code
Once your test passes, then you can focus on refactoring the code. During the refactoring phase, you improve the quality of your code. In addition, Refactoring is much easier now that you have a test to let you know that you haven’t broken anything.
The refactoring phase reveals if you have properly tested behavior or if you have tested implementation details. If your tests break while refactoring, but the behavior remains the same, that’s a sign that you need to change how you wrote your tests.
Want to see this in action?