TDD, BDD, ADD, SDD, EDD: Which Do You Actually Need? A Practical Guide for the AI Era
DEV Community

TDD, BDD, ADD, SDD, EDD: Which Do You Actually Need? A Practical Guide for the AI Era

TL;DR

Five acronyms, one question: how do you know the software does what you wanted?

  • TDD verifies your code.
  • BDD verifies your behaviour.
  • ADD / ATDD verifies your agreement.
  • SDD verifies the work of your AI coding agent.
  • EDD verifies the AI output you ship.

You don't pick one. You stack them - and this article tells you where each one goes.

Read further for deepdive.

The Question Behind All Five

Five terms, five philosophies. And if you've been drowning in newsletters lately, you've probably felt the same confusion: is this a testing strategy? A process? A mindset? Are they fighting each other?

My take on this is: none of these are really "testing strategies." They're all answers to the same question, asked at different moments in software history: How do you know the software does what you want?

We are in the phase - AI writing the code. Writing code got cheap, fast, and almost free. Verifying code got more expensive, not less. These five practices, in different ways, are all verification tools.

Let's meet the family, one by one.

The Family Tree (1990s β†’ 2026)

1990s 2003-06 2000s 2024-26 2025

  • TDD - Kent Beck (Extreme Programming)
  • BDD - Dan North (grew out of TDD)
  • ADD - agile testing (usually written as ATDD)
  • EDD - Hamel Husain & Shreya Shankar, Airbnb practice
  • SDD - GitHub Spec Kit + OpenSpec

The split is not a coincidence. The first three exist to prevent building the wrong thing. The last two exist because a new builder entered the room - one that's fast, tireless, and has zero stake in your product.

Acronym Full name What it verifies When it showed up
TDD Test-Driven Development Your code Late 1990s - Kent Beck, Extreme Programming
BDD Behaviour-Driven Development Your behaviour 2003 - Dan North
ADD Acceptance-Driven Development (usually written ATDD) Your agreement Agile years
SDD Spec-Driven Development Your AI coding agent's work 2025 - GitHub Spec Kit, OpenSpec
EDD Eval-Driven Development Your shipped AI's output 2024-2026 - the AI industry

TDD: The Loop That Changed Everything

Test-Driven Development was formalized by Kent Beck in the late 1990s, as part of Extreme Programming. The standard summary of the loop:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”Œβ”€β”€β”€β–Ίβ”‚ RED β”‚write the next failing test
β”‚β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
β”‚β–Ό
β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚β”‚ GREEN β”‚write just enough code to pass
β”‚β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
β”‚β–Ό
β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚β”‚ REFACTORβ”‚clean it up, tests stay green
β”‚β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
β”‚β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ (repeat, forever)

Why it works: Two benefits, per Martin Fowler. First, your code is self-testing - you can only write production code in response to making a test pass.

Second, and the underrated one: thinking about the test forces you to think about the interface first. You design how the thing is used before deciding how it's built.

The most common way people screw up TDD is skipping step three. No refactoring means a messy aggregation of code fragments - the tests stay green, the code doesn't.

BDD: Tests That Read Like English

Behaviour-Driven Development was coined by Dan North. North was teaching TDD and kept hitting the same wall: beginners asking where do I start, what should I test, what do I call this, why did it fail? His answer was a reframe. Stop saying test. Start saying behaviour.

BDD has three parts:

  1. Discovery - structured conversations around real-world examples of how the system should behave.
  2. Formulation - writing those examples down in a human-readable, executable format (usually Gherkin).
  3. Automation - wiring the examples to the running system as tests.
Feature: User login
  Scenario: Successful login
    Given a registered user exists
    When the user submits valid credentials
    Then they are redirected to the dashboard

The mechanics worth knowing:

Test names are sentences, not testFailsForDupes.

The "should" template: every test fits the class should do something. The word "should" quietly invites you to challenge the premise - should it, really? That's how stale assumptions get caught.

The story shape: As a [X], I want [Y], so that [Z]. The "so that" forces you to state the value - and half of all feature requests die there, honestly and quickly.

A ubiquitous language (borrowed from Domain-Driven Design): the same words appear in the requirement, the test, and the code. When everyone shares a vocabulary, miscommunication - one of the most expensive bug sources in software - drops.

BDD is for deterministic systems. The output of a login form is either correct or it isn't. assert redirect_url == "/dashboard" is a valid test.

Tools: Cucumber, SpecFlow, Behave, pytest-bdd, Jest + Testing Library.

ADD: The Contract You Sign Before the Machine Starts

Acceptance-Driven Development / ATDD (Acceptance Test-Driven Development). The idea is simple: before anyone writes a line of code, the team - developers, testers, and the business person - writes the acceptance criteria for the story. In natural language. End to end.

  • ADD - acceptance: "what does done mean?" the team signs off BEFORE any code - the contract
  • BDD - behaviour: "what should it do?" Given/When/Then scenarios in plain English
  • TDD - unit: "does this function work?" red-green-refactor, smallest, fastest, cheapest

Read that pyramid from the bottom up: TDD checks the parts, BDD checks the behaviour, ADD checks the agreement. Each level is slower, coarser, and closer to the business.

A story in full ADD dress:

Story: As a user, I want to reset my password, so that a compromised account is less dangerous.

Acceptance criteria:

  • A reset link expires after 30 minutes.
  • A reset link can only be used once.
  • A user with 2FA must re-verify their identity after a reset.
  • The account is logged out everywhere after a reset.

That's the whole practice. The criteria are written before implementation, reviewed by the people whose jobs depend on the feature, and become the tests the finished feature must pass.

Each of the three roles gets something:

  • The developer knows the exact shape of "done" before starting - and the shape rarely changes mid-build.
  • The tester designs the verification while it's still cheap to change, not after the code exists.
  • The business person signs off on behaviour in a language they actually read.

SDD: The Spec Is the Source of Truth

Spec-Driven Development is the newest heavyweight.

  • GitHub Spec Kit (github/spec-kit) - GitHub's open-source toolkit (140k+ stars as of Oct 2026) for spec-driven work with AI coding agents; bug-fix and idea-assessment flows ride along, but SDD is the flagship.
  • OpenSpec (openspec.dev, by Fission-AI) - a lighter-weight community framework where specs live in your repo as first-class artifacts (73k+ stars).
  • AWS Kiro - an IDE with the spec-driven flow (specs, requirements, project steering docs) baked into the editor; where many teams first meet SDD.

The fundamental problem SDD solves: if you let an AI agent write both the component and the tests for it, the agent will unconsciously write tests that pass - not tests that verify. SDD breaks that cycle by locking the spec before any code exists. The spec is written by a human. The code is written by the agent. The spec is the non-negotiable contract between them.

OpenSpec's mental model is the contract and the contractor: a contractor who shows up with no blueprint builds whatever they think you meant. OpenSpec is the contract. The agent is the contractor.

The Spec Kit flow:

/speckit-constitution once per project: principles (quality, tests, style) β†’ /speckit-specify what & why β†’ /speckit-plan stack & constraints β†’ /speckit-tasks the spec, broken into an ordered task list β†’ /speckit-implement β†’ /speckit-converge does the code match the spec?

Two details deserve emphasis. The constitution is the spec for specs - your project's non-negotiables, written once. Converge is a verb the pre-AI world didn't need: TDD asks "do the tests pass?"; SDD asks something stricter - does what was built match what was specified, end to end? The spec is the source of truth; the code is the claimant.

The OpenSpec flow:

  1. /opsx:explore optional: a no-stakes thinking partner - reads the codebase, shapes the plan
  2. /opsx:propose <feature> agent writes the spec. No code yet.
  3. /opsx:apply <feature> agent writes code strictly following the spec
  4. /opsx:archive <feature> the change is folded into the main spec, permanently

Lighter than Spec Kit: each change is a folder of plain Markdown - proposal.md, specs/ (requirements and scenarios), design.md, tasks.md - reviewed by a human before any code is written. Command spellings vary by tool (/opsx-propose, $openspec-propose); openspec init prints the right form for yours.

Why it works (and why it's not "just a good prompt"): Agents are bad at holding thirty requirements in their head across a long session. They're good at following a written document step by step. A spec is a leash with a purpose: it keeps intent outside the model - in a file that survives session restarts, model swaps, context windows, and team changes.

Tell an agent a feature in chat, and the intent dies with the conversation. Write it in a spec, and it outlives everything except your product.

EDD: The TDD of the AI World

Eval-Driven Development that exists because of a specific technical fact: LLM output is probabilistic. You build a support bot. You write assert response == "Your order has shipped." and you've written a test that will fail on the first Tuesday of the month, for reasons you cannot predict. Unit tests assume determinism. Probabilistic output breaks that assumption, so the whole verification story has to be rebuilt. That rebuild is EDD.

The term was formalized in methodology by Hamel Husain and Shreya Shankar, and got an academic process model in the arXiv paper "Evaluation-Driven Development and Operations of LLM Agents".

The vocabulary in 60 seconds

An eval is a test that measures whether your AI system is doing what you want. It returns a score or a pass/fail on a set of real or representative examples.

Product evals vs model benchmarks: benchmarks (MMLU, GPQA, Terminal-Bench) say how a model does on generic tasks. They say almost nothing about your order-cancellation agent. Product evals measure your product against your users' actual needs.

A trace is the complete record of one session: every message, tool call, and retrieval from first query to final answer. Traces are your raw material - you can't find failures you can't see.

The loop (in the correct order)

  1. RUN the system, collect traces
  2. ERROR ANALYSIS read 30-100 traces, note every failure, group notes into a failure taxonomy
  3. BUILD an eval for each failure that matters - cheap first: code assertions, regex, JSON checks, "did it call the right tool?" - expensive last: LLM-as-judge for judgment calls, validated against 100-200 human labels before trusting it
  4. FIX β†’ re-run β†’ improved, without regressing? new traces, new failures, repeat

Hamel and Shankar put it in their own FAQ: on serious projects, 60-80% of development time goes to error analysis and evaluation - that is, looking at data, not building dashboards. That ratio is the practice. If your eval workflow is 90% dashboard and 10% looking, you have the wrong workflow.

Two more rules of the road: Binary beats Likert. A pass/fail per failure mode beats a fuzzy 1-5 rating. Change one variable at a time - prompt, model, or RAG config - then measure. Otherwise you can't tell what actually improved.

The part everyone gets wrong

The naive version of EDD says: "build a golden dataset and a scoring rubric first, then develop." Here's the correction, from the field's most-cited authority. Hamel Husain's own answer to "Should I practice eval-driven development?" is generally no. His reasoning: unlike traditional software, where failure modes are predictable, LLMs have an infinite surface area for potential failure. You can't anticipate what will break. Writing evals before the system exists means writing evals for failures you imagined - wasted effort, and it blocks you on questions you can't answer until the system exists.

The version that works: Do error analysis first. Write evals for failures you found, not failures you guessed. The golden dataset is real and important - but it grows out of error analysis, as a version-controlled set of representative examples and expected quality. It's not something you author on a whiteboard in week one.

One exception: if you have a constraint where you already know exactly what success looks like - "the model must never mention competitor X" - writing that evaluator early is fine. It's a known boundary, not a prediction.

Tools: LangSmith, Braintrust, RAGAS, Arize Phoenix, Weights & Biases Weave.

When to use EDD

  • Any LLM-powered feature: chatbots, RAG systems, agents, summarizers, classifiers.
  • Any time you change a prompt, model, or retrieval setup and can't tell if it got better or worse. (You can't. Run the evals.)
  • Before you trust a "fix" to an AI feature. If it doesn't show up in the evals, it didn't happen.

When EDD is the wrong tool

  • Deterministic code with no AI in the loop. That's TDD's job.
  • Week one of a new AI feature, when you have no traces yet. (You can bootstrap error analysis on synthetic data - that's standard.)
  • When the team's first instinct is to buy an eval platform instead of reading 30 traces. The platform is step four, not step one.

SDD vs EDD: How the Two Split

This is the most common confusion in the field, so here's the clean split: SDD is for people who are coding and creating applications using coding agents. EDD is for people who are building AI-powered features as their prod

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.