When practicing Test-Driven Development, we’re supposed to write a test first. I’ve heard developers say “it doesn’t matter if we write the test before or after the implementation, as long as we do it.“
This is how I think of it:
Writing the implementation first, and then writing tests for it, sounds like implementation-driven tests. Such tests are shaped by the implementation and end up reflecting the implementation’s dependencies and how it works, unless the tests are refactored into BDD-style specs (see the differences between TDD and BDD), which is hardly ever the case.
Writing the test first, and then the implementation, drives the implementation. Test-driven development. That’s why many people (myself included) rather think of TDD as test-driven design, placing focus on the design aspect of the practice.
“Why does that matter?”
Shift in perspective.
By quickly jumping into writing code, we’re also quickly distancing ourselves from the real-world problem we’re supposed to solve.
“So, there’s no value in writing tests for existing (legacy) code?”
Yes, there is. Please do so. And once the tests are written, refactor them so to document the feature and NOT the implementation. In other words, they document why the code exists, not how it works.
I believe reading tests should go like this:
- WHY this feature exists
- HOW the API supports it (input/output)
- WHAT supports the API (classes, components, methods, functions…)
In that order.
The tests/specs are not for a business feature, but instead, a technical feature?
Same thing: Why ➡️ How ➡️ What.