In this post, I show the day to day differences between TDD (Test Driven Development) and development without tests or write tests after the feature is complete (TLD) .
- TDD takes less time than non-TDD approaches because it reduces manual testing, which takes a lot of time.
- Tests are a safety net. In TDD, we have a safety net while coding, not only after we finish the development.
- TDD is a methodology that helps developers to focus and work in baby steps, those reducing the cognitive load.
- TDD encourages clean code.
- Life is easier with TDD because we start with a small amount of code, which slowly grows.
In this approach, we repeatedly:
- Choose scenarios for testing.
- Write code for those scenarios.
- Test from outside and manually examine that the scenario works correctly by, for example, viewing the data in the UI, looking at the results of API calls, and performing DB queries.
- Fix the code until the scenario works as planned.
When do we check previous scenarios still work? I guess each developer checks at a different time: when finish to develop the feature, after each scenario, and even by the number of code changes.
This approach is similar to development without tests except that we write tests after we developed the feature in order to validate the feature works correctly.
The overall idea is to write code incrementally. We write code for a specific scenario while always validating that other scenarios still work. Also, we care about clean code, but at a separate stage.
For each scenario, we:
- Write a test that represents one scenario. We run the test, and it fails* because we didn’t write any code for it to pass(Compilation errors count as failures)
- Write the minimal code for the test to pass.
- Refactor the code.
*If the test doesn’t fail, it usually means that we wrote more than the minimal code at a previous iteration, or that the test is equivalent to an existing one.
In non-TDD approaches, we test our code manually by reproducing the same flow over and over again. Reproduction of the flow can include: application loading, login, get to the relevant screen and press a button. The feedback is slow and requires us to remember a sequence of actions.
In TDD, we run all the tests with a press of a button. A unit test usually takes a few milliseconds; an integration test usually takes a few seconds.
TDD takes less time than writing tests in the end because the outcome is the same, but while coding, we still need to test somehow, so we perform manual testing. I believe that TDD also takes less time than develop without tests because the manual tests take more time than write tests.
TDD gives us a simpler and faster way to test our code.
We tested a few scenarios, and we are now implementing the next one. We changed the code, so we should retest the existing scenarios.
In the Non-TDD approach, we test manually. Manually testing takes time, and it’s a repetitive and precise task — not something we humans excel at. In the best case, we documented the scenarios; in the worst case, they are inside our head. What are the chances we really retest all scenarios? Even if we documented the scenarios, do we really retest them all? Or do we skip some because the process is long and repetitive? (I would even say boring).
In TDD, with a press of a button, we test all existing scenarios after each code change.
TDD is a methodology that defines a work order. Each task has its time: write a test, write production code, and refactor.
In non-TDD approaches, everyone has their methodology, even if they are not aware of it.
Focusing on a specific scenario and the three stages create a process of small and defined steps — Baby steps 👶. This kind of process creates focus and lowers the cognitive load.
I noticed that for me:
- The refactor part helps me to avoid refactoring while coding. More than once, I started to refactor while writing code and ended with messy and broken code. I had to discard the code. 😢
- Focusing on a specific scenario helps me ignore other scenarios while implementing it, which reduces my cognitive load.
In non-TDD approaches, every developer decides when to refactor. From my experience, we postpone the refactor to the end of the feature. The problem is that at some point soon, we suffer from the mess we made during the development.
In TDD, there is a dedicated time for refactoring. Because it is at the end of each cycle, we work with more maintainable code while developing.
There is a better chance that working in TDD will produce a cleaner code than the non-TDD approaches, but it depends a lot on the developer.
I know it sounds like a disadvantage, but…
In TDD, we start with a small amount of code, which slowly grows. At every stage in the development, we have less code: less code to read, less code to debug, less code to navigate through =>Life is easier. 😌
I hope I convinced you to try TDD. You are welcome to contact me, and I will be happy to help you adopt it.