Tests Are Not Documentation
There’s a phrase repeated so often in software circles that it’s almost treated as gospel: “Tests are documentation.” It sounds clear and reassuring, but it hides a wrong assumption. It mixes different things together and relies on wishful thinking.
You often hear this idea inside development teams, where people genuinely believe in it and try to follow it as a principle. At the same time, those same teams often worry about reducing onboarding time for new developers. In practice, however, these two goals rarely align.
One could argue that a newcomer should simply interact with team members to gather the missing context. In reality, that expectation is not always practical. Software development teams are not sales departments, and most engineers do not spend their days practicing clear verbal explanations of systems and decisions.
I’d like to offer a different view.

Tests Capture Behavior, Not Intent
Imagine a system built on a deliberate architectural idea say, CQRS, event sourcing, or layered ports and adapters. Now look at a unit test verifying that a handle method emits the correct event in response to a valid command. It may be beautifully crafted: a precise name like shouldEmitEventWhenValidCommandIsReceived, neatly composed fixtures, and clear assertions.
But what, exactly, does it document?
Not the rationale behind CQRS. Not the decision to use events instead of direct writes. Not the strategic choice of interface segregation. It documents an example. A symptom, not a cause.
The Problem of Abstraction
Architecture is high-level abstraction. It's about why we built the system this way, what trade-offs we accepted, which boundaries we intend to keep stable. Tests, on the other hand, operate at a much lower level — concrete inputs, concrete outputs, specific cases. They serve a different purpose.
Confusing architectural documentation with tests is like confusing a subway map with the instructions for opening a train door. Both have their place. But you can’t plan your journey by staring at the handle.
What Tests Do Well and What They Don’t
Tests excel at:
- Verifying correctness of specific behavior.
- Guarding against regressions.
- Expressing contracts between modules.
But they fall short when it comes to:
- Explaining why things are the way they are.
- Revealing relationships across architectural layers.
- Capturing design rationale or constraints.
Even with Given-When-Then, describe blocks, and well-named scenarios, you’re still operating in the world of examples, not intentions.
Living Documentation Is More Than Tests
If we want code to speak clearly, tests alone won’t suffice. We need:
- Architecture notes — concise, up-to-date design overviews.
- Architecture Decision Records (ADRs) — formalized justifications for choices.
- In-code comments — not "what" but "why."
- Domain-oriented DSLs or BDD specs — where language mirrors the problem space.
These give developers a view not just into what the system does, but why it’s shaped the way it is.
Conclusion
Tests are indispensable. They form the safety net beneath our code, enabling fearless change. But to call them "documentation" is to ignore a deeper truth: that knowing what code does is not the same as understanding why it exists in the first place.
Good code speaks at multiple levels. Don’t make your team piece together intention from fragments give them a map, not just the terrain.
To be continued...