Straight Talk: When They Help, When They Don't
Here's the phase the conference talks rarely give you. Everything below is judgment - a read after watching these techniques help on some projects and quietly waste everyone's time on others. Treat it as opinion you can argue with, not law. The facts are in Phases 1 and 2; this is about taste.
The single most useful thing to internalize: TDD and BDD are tools, not religion. A tool is something you pick up when it fits the job and put down when it doesn't. The moment a technique becomes a thing you do because that's what good developers do, rather than because it's solving a problem in front of you, it has stopped helping.
When TDD genuinely shines
⚖️ Judgment - but widely shared.
Well-understood logic with clear right answers. Parsers, formatters, pricing rules, date math,
validation, algorithms - anything where you can state the expected output for a given input before you
write the code. This is TDD's home turf, exactly like the format_price example in
Phase 1. The test-first loop is fast and the tests are valuable forever.
Bug fixes. This one's almost free money. Before you fix a bug, write a test that reproduces it - and watch it fail. Now you've proven you understand the bug, your fix has a target, and you've permanently inoculated the codebase against that exact regression. Even people who don't otherwise do TDD often do this.
Code with tricky edge cases. When the hard part is "what about empty input, negative numbers, the leap-year case, the off-by-one" - enumerating those as failing tests first turns a fuzzy worry into a concrete checklist you can drive to green one at a time.
When TDD fights you
⚖️ Judgment.
Exploratory work, where you don't yet know what you want. You can't write a test for behavior you haven't decided on. When you're spiking a prototype, learning an unfamiliar API, or feeling out a design, test-first inverts badly - it demands answers you don't have. Explore first, then TDD the version you decide to keep. Forcing TDD here means writing, and rewriting, tests for code you throw away an hour later.
UI and visual work. Whether a layout looks right, whether an animation feels smooth, whether the
spacing is pleasant - these aren't expressible as assert. You can test the logic behind a UI (does the
button dispatch the right action?), and that's worth doing test-first. But the visual layer itself is judged
by eyes, not assertions. Trying to TDD "the page looks good" produces brittle tests that break on every
plain design tweak.
Throwaway code and one-off scripts. If you'll run it once and delete it, the test is overhead with no payoff. Be clear-eyed about whether it's really throwaway, though - plenty of "temporary" scripts outlive their authors.
Here's the same trade-off as a table you can scan:
TDD pays off TDD gets in the way
──────────── ───────────────────
logic with clear right answers exploratory / prototyping
bug reproduction + fix UI look-and-feel
tricky edge cases code you'll delete tomorrow
things you'll change again later a design you haven't settled yet
When BDD pays for itself
⚖️ Judgment.
BDD's extra layer - the English scenarios, the step definitions - earns its keep in exactly one situation: when non-developers actually read and shape the scenarios. A product owner who reviews the Given/When/Then before you build, a compliance requirement traceable to plain-language rules, a domain complex enough that getting the requirements right is harder than the code - that's where BDD turns its overhead into a profit. The shared, readable spec prevents the most expensive bug of all: building the wrong thing correctly.
When BDD is just overhead
⚖️ Judgment.
If the developers are the only people who ever read the scenarios, you're maintaining a translation layer with no one on the other end - a plain unit test, which any developer reads fine, wrapped in English-parsing plumbing that has to be kept in sync. For a developer-only audience, plain TDD-style tests are usually clearer and cheaper. BDD without business readers is BDD's costs without its benefit.
⚠️ The big trap: cargo-culting the ritual
This is the failure mode I see most, and it's worth naming sharply.
📝 Terminology. Cargo-culting means imitating the visible rituals of a practice while missing the substance that made it work - going through the motions and expecting the magic to follow.
In testing, cargo-culting looks like:
- Writing tests after the code, then reordering the commits so it looks test-first. The ritual is performed; the design benefit (letting the test shape the code) never happened.
- Chasing 100% coverage with tests that assert nothing meaningful - tests that pass no matter what the code does, there only to make a number go up.
- Wrapping every internal, developer-only test in Given/When/Then because "we do BDD here," with no stakeholder in sight.
- Insisting a teammate redo working, well-tested code because it wasn't written in the approved order.
The tell is always the same: the ritual is present, but the benefit it exists to produce is absent. Catch yourself (or a team) doing the ceremony without the payoff, and that's the signal to stop and ask what problem you're actually solving.
The plain takeaway
- TDD is a sharp tool for well-understood logic, bug fixes, and gnarly edge cases - and an awkward one for exploration and visual work. Use the loop where answers exist before the code; explore freely where they don't.
- BDD is a collaboration layer that pays off when real non-developers read the scenarios, and is pure overhead when they don't.
- Neither is a measure of your worth as an engineer. They're techniques. Reach for them when they solve a problem you have, set them down when they don't, and never perform the ritual for its own sake.
The developers who get the most out of these techniques aren't the most devout - they know exactly when not to use them.
Recap
- TDD shines for clear-answer logic, bug reproduction, and edge cases; you'll write those tests forever and be glad.
- TDD fights you on exploratory, prototype, and look-and-feel UI work - explore first, test the keeper.
- BDD pays off when non-developers read and shape the Given/When/Then scenarios; otherwise it's a translation layer with no audience.
- Cargo-culting - the ritual without the benefit - is the trap: test-first theater, meaningless coverage, BDD with no business readers.
- Tools, not religion. Pick the technique that fits the job in front of you, and drop it when it doesn't.
That's the plain picture: what TDD and BDD are, how to run each loop, and the judgment to use them where they genuinely help.
← Phase 2: BDD - Describing Behavior · Guide overview
Related guides: Your First Unit Test · Unit, Integration & E2E
Check your understanding 3 questions
1. Where does TDD genuinely shine?
2. Where does TDD fight you?
3. What is cargo-culting in testing?