EngineeringBest Practices

Spec-Driven Development vs Test-Driven Development

Shiplight AI Team

Shiplight AI Team

Updated on July 15, 2026

View as Markdown
Illustrated Shiplight blog cover: two glossy floating panels balanced side by side, a spec-first blueprint on the left and a test-first green checklist on the right, on a soft divider.

Spec-driven development and test-driven development both put intent into an executable artifact before the implementation exists, but they operate at different altitudes. Test-driven development starts each small change with a failing test that pins one behavior. Spec-driven development starts a whole feature with a structured, written specification that a coding agent then plans, breaks into tasks, and implements. Test-driven development answers "does this unit do what I just claimed?" Spec-driven development answers "did we build the thing we agreed to build?" Neither replaces the other, and behavior-driven development sits between them with a shared, plain-language description of behavior.

The reason the comparison matters now is that AI coding agents changed the economics of writing that intent down. When a human wrote every line, a specification often went stale the moment coding started. When an agent reads the specification and generates the code, the specification becomes the primary input, not documentation nobody reads. That shift is why spec-driven development moved from a nice practice to a named methodology with tooling, and why teams already fluent in TDD are asking how the two fit together.

This guide defines each methodology, compares them on the axes that distinguish them, and is honest about where all three stop. The short version: writing intent down, at any altitude, does not prove the running software matches it. That gap is the subject of the last two sections.

What test-driven development actually is

Test-driven development is a technique for building software by writing a test before the code that satisfies it. Kent Beck developed it in the late 1990s as part of Extreme Programming and popularized it in the 2003 book Test-Driven Development: By Example, which moved the practice into the mainstream.

The rhythm is three steps, usually summarized as red, green, refactor:

  1. Red. Write a small failing test for the next bit of behavior you want.
  2. Green. Write the least code needed to make that test pass.
  3. Refactor. Clean up both the new and existing code while keeping every test green.

The discipline is deliberately tight. Each cycle covers a single, small behavior, and the test is written by the same engineer implementing the code, in the same programming language, living beside the code in the repository. As Martin Fowler notes, the most common way to get TDD wrong is skipping the refactor step, which leaves you with a passing but messy pile of fragments.

The strength of TDD is fast, local feedback and a design pressure that pushes toward small, testable units. Its limit is scope. A green unit-test suite tells you each part does what its author claimed. It does not tell you the parts add up to the feature a product manager described, and it rarely exercises the full path a real user takes through a browser.

Where behavior-driven development fits

Behavior-driven development grew directly out of TDD. Dan North introduced it in a 2006 article as a response to a recurring problem: teams struggled with where to start testing, what to test, and how to name tests so they described behavior instead of implementation. BDD reframed a "test" as a specification of behavior written in language a non-programmer could read.

The organizing structure is Given-When-Then, a format Dan North and Chris Matts developed to break a scenario into three parts:

  • Given the state of the world before the behavior.
  • When the behavior happens.
  • Then the outcome you expect.

Dan North later formalized this into Gherkin, the structured, human-readable syntax used by tools such as Cucumber. The point of Gherkin was never the syntax. It was to create one artifact that product, QA, and engineering could all read and agree on, so that "done" meant the same thing to everyone before code was written.

BDD's contribution to the spec-versus-test question is the shared vocabulary. It raised intent from code-level assertions to plain-language scenarios, and in doing so it prefigured a lot of what spec-driven development now does at feature scale.

What spec-driven development adds

Spec-driven development puts a written specification at the center of the workflow and treats it as the executable source of truth that a coding agent implements from. Instead of prompting an agent feature-by-feature and hoping the result matches your intent, you describe what to build, refine it through structured phases, and let the agent generate the implementation from the refined artifact.

GitHub's open-source Spec Kit is the clearest reference implementation of the methodology. Its core loop runs in four phases, each producing a Markdown artifact that feeds the next:

  1. Specify captures functional requirements and user stories, deliberately without technology choices.
  2. Plan sets the architecture, tech stack, and implementation strategy.
  3. Tasks breaks the plan into ordered, dependency-aware work items.
  4. Implement executes those tasks to build the feature.

Spec Kit adds one more artifact worth calling out: a constitution.md file of non-negotiable project principles that constrain every phase. The GitHub team frames the goal as making specifications executable, so they generate working implementations rather than merely guiding them. Spec Kit works with 30-plus AI coding agents, including Claude Code, GitHub Copilot, and Gemini CLI.

The altitude here is the whole difference. A TDD test pins one unit. A BDD scenario pins one user-visible behavior. A spec-driven specification pins an entire feature, including the requirements, the plan, and the task breakdown, and hands all of it to an agent as structured context instead of an ad-hoc prompt.

SDD vs TDD vs BDD, side by side

The three methodologies are easy to conflate because all of them write intent down first. They differ sharply on who writes it, at what granularity, and what the resulting artifact actually checks.

AxisTest-driven developmentBehavior-driven developmentSpec-driven development
What is written firstA failing unit testA Given-When-Then scenarioA feature specification, plan, and task list
GranularityOne small unit behaviorOne user-visible behaviorA whole feature or system slice
Who authors itThe implementing engineerEngineering plus product and QA togetherA human, refined with an AI agent
LanguageThe production programming languageStructured plain language (Gherkin)Structured Markdown prose
Where it livesBeside the code, in the repoIn feature files in the repoIn a spec directory in the repo
What it verifiesThe unit does what its author claimedThe scenario behaves as describedThe build matches the agreed feature
Primary feedback loopSeconds, at the developer's deskMinutes, at the acceptance levelPer feature, before and during implementation

Read across the rows and a pattern appears. As you move from TDD to BDD to SDD, the artifact rises in altitude and widens its audience, from one engineer's local check to a cross-functional agreement to a full feature contract an agent can execute. What none of the columns guarantees on its own is the row that matters most to a user: that the running application, in a real browser, does what the artifact says.

What all three share, and where they stop

Every methodology here is a way of making intent executable before or alongside the code. That is a genuine strength, and it is exactly why teams should keep doing it. But each one verifies a proxy for the real thing:

  • A green unit suite proves your functions behave as their author expected. It does not click through the actual UI.
  • A passing Gherkin scenario proves the step definitions behave. Those step definitions are still code someone has to keep in sync with the interface.
  • A completed spec-driven implementation proves the agent finished the tasks. It does not prove the feature works when a person uses it.

In an agent-speed world this gap widens fast. When an agent ships a UI change every few minutes, the question is not "was there a spec?" or "did the units pass?" It is "does the running software still match the intent right now?" Answering that reliably needs a fast verification loop that exercises the real product, not a stand-in.

This is the layer Shiplight provides, and it is deliberately methodology-agnostic. Shiplight plugs into your coding agent as an MCP server and gives it eyes and hands in a real browser. When the agent makes a change, /shiplight verify confirms the UI actually looks and behaves right, in context, before a reviewer ever sees the pull request. The acceptance criteria you already wrote, whether they came from a TDD story, a Gherkin scenario, or a spec-driven feature file, become maintained end-to-end tests through /shiplight create-yaml-tests, where the agent walks the app and authors them for you.

Those tests are readable YAML authored from intent rather than brittle selectors, they live in your own git repository, and they self-heal in a real browser with heals surfacing as reviewable pull request diffs instead of silent rewrites. That design lets acceptance criteria stay executable as the product moves, which is the same promise TDD, BDD, and SDD each make at their own altitude.

Choosing, or combining, the methodologies

These are not mutually exclusive, and the strongest teams compose them. Run spec-driven development at the feature level to align on what to build, keep test-driven development at the unit level for fast local design feedback, and borrow BDD's Given-When-Then to phrase acceptance criteria both humans and agents can read. The methodologies stack because they operate at different granularities.

What none of them supplies is proof at the top of the stack. A specification, a scenario, and a unit test are all statements of intent. The one thing an agent-speed team cannot skip is a loop that checks the running product against that intent continuously, in the browser a customer would actually use. For more, see the executable intent playbook and the tradeoffs between AI-generated and hand-written tests. New to the top of this stack? Start with what spec-driven development is and how test-driven development changes in the AI era.

Key Takeaways

  • TDD, BDD, and SDD differ by altitude, not intent. TDD pins one unit, BDD pins one behavior, and spec-driven development pins a whole feature that an agent implements.
  • Spec-driven development rose with coding agents. When the agent generates the code from your specification, the specification becomes the primary input rather than documentation nobody reads.
  • BDD is the bridge. Given-When-Then, introduced by Dan North in 2006, raised intent from code-level assertions to plain-language scenarios a whole team can agree on.
  • All three verify a proxy. Green units, passing scenarios, and finished tasks each check a stand-in, not the running product a user touches.
  • The missing layer is browser-level verification. At agent speed you need a loop that proves the live software matches intent, and that loop works regardless of which methodology produced the intent.

Frequently Asked Questions

What is the difference between spec-driven development and test-driven development?

Spec-driven development starts a feature with a written specification that a coding agent plans and implements, so intent is captured at the feature level. Test-driven development starts each small change with a failing unit test that the same engineer then makes pass, so intent is captured at the unit level. They operate at different altitudes and can be used together on the same project.

Is spec-driven development just BDD with a new name?

No, though they share DNA. Behavior-driven development, introduced by Dan North in 2006, describes individual behaviors in Given-When-Then form for a shared human-readable acceptance check. Spec-driven development captures a full feature, including requirements, a technical plan, and a task breakdown, and is designed for an AI coding agent to implement from directly.

Do I have to choose one methodology?

No. The three compose well because they work at different granularities. Many teams run spec-driven development at the feature level, test-driven development at the unit level, and borrow BDD's Given-When-Then to phrase acceptance criteria that both people and agents can read.

Does writing a spec or a test prove my software works?

Not by itself. A specification, a scenario, and a unit test are all statements of intent, and each verifies a proxy for the running product. Proving the live application matches that intent requires a verification loop that exercises the real UI in a browser, which is what Shiplight adds on top of whichever methodology you use.

How does Shiplight fit with these methodologies?

Shiplight is methodology-agnostic. It plugs into your coding agent to verify UI changes in a real browser as they are built, then turns your acceptance criteria into maintained end-to-end tests written as readable YAML in your own repository. Whether the intent came from TDD, BDD, or spec-driven development, Shiplight closes the loop by proving the running software matches it.