Claude Code Test-Driven Development: A Step-by-Step Workflow

Claude Code Test-Driven Development: A Step-by-Step Workflow

Claude Code test-driven development means you ask Claude to write a failing test first, then the smallest code that makes it pass, and only then tidy up. You stay in charge of the rules, and Claude does the typing and the test runs. The result is code that comes with a safety net from the very first line.

Many people let Claude write the code first and add tests later, or never. That works until a small change quietly breaks something. In this guide you will follow a real red, green, refactor loop in a throwaway project, see exactly what Claude did at each step, and learn the prompts that kept it on track.

This post answers one of the most common Claude Code questions. It is part of our Claude Code tutorials collection, so browse all our Claude Code tutorials for more guides like it.

Tested with Claude Code v2.1.316 on 2026-11-02. We tested on macOS with Python’s built-in unittest; the same prompts work with any test runner.

Quick Answer: How to Do TDD With Claude Code

Do TDD with Claude Code in four moves. Tell it to write the tests but not the code, run them and watch them fail, ask for the smallest code that passes, then repeat for each new rule. Keep the test command in your CLAUDE.md so Claude never has to guess it.

StepWhat you ask ClaudeWhat you should see
1. RedWrite the tests. Do not write the code yet. Run them.The run fails
2. GreenWrite the smallest code that makes them pass.All tests pass
3. New ruleAdd this test first, show it fail, then fix the code.One failure, then all green
4. RefactorClean up the code and run every test again.Still all green

A test you never saw fail proves nothing. Make Claude show you the red run every time.

What Is Claude Code Test Driven Development?

Test-driven development, or TDD, is a way of writing code in very small loops. You write a test that describes one behavior, you watch it fail, you write just enough code to pass it, and then you clean up. Developers call the three stages red, green and refactor.

The order matters because the failing test proves the test can actually catch a problem. If you write the code first, a test that passes might be passing for the wrong reason. We saw this happen in our own run, and we show it below.

Why TDD fits Claude Code so well

Claude Code works in a loop of gathering context, taking action and checking results. A test suite is the best “check results” step you can give it. The official best practices page asks whether Claude knows what done looks like, and names a failing test it has to turn green as one good answer.

Official Claude Code best practices page with the line about a failing test it has to turn green highlighted
The best practices page lists a failing test that has to turn green as a clear definition of done.

In other words, TDD gives Claude a target it can verify by itself. You do not have to read every line to know whether it worked, because the tests tell you. You can read more about how Claude Code decides when it is finished in our guide to the /goal command.

Set Up a Practice Project

We made a throwaway folder with one file. It is a CLAUDE.md that tells Claude how to run the tests and to stay inside the Python standard library. If you have never written one, our guide to the CLAUDE.md file explains the idea, and the CLAUDE.md template gives you a copy-ready example.

# Demo project

Tiny Python practice project. Run the tests with: python3 -m unittest -v
Use only the Python standard library. Keep files small.

That second line of the file is the important one. The official docs say the single most useful line in your CLAUDE.md is the command that runs your tests. When Claude knows it, every red and green run uses the same command.

Start Claude Code with fewer approval prompts

TDD means many small file edits and test runs. To keep the demo smooth we started Claude Code in accept edits mode and pre-approved only Python commands.

claude --permission-mode acceptEdits --allowedTools "Bash(python3:*)"

File edits then go through without a prompt, and python3 commands run on their own. Anything else, such as deleting files, would still ask first. Our guide to permission modes explains every option, and you can press Shift+Tab inside a session to switch modes.

Claude Code TDD Step 1: Write Tests First (Red)

Our goal was a small function called slugify that turns a title into a web-friendly slug. For example, “Hello, World!” should become “hello-world”. We gave Claude the rules and, importantly, told it not to create the code file yet.

Let's do TDD. Write test_slugify.py for a function slugify(text) that will
live in slugify.py: lowercase output, spaces become hyphens, punctuation is
removed. Do NOT create slugify.py yet. Run python3 -m unittest -v, then
reply in two short lines.

Claude wrote an 18-line test file with three tests, ran the suite and reported the failure. The run was red because the module did not exist yet, which is a valid first red step.

Claude Code terminal showing the test file being written and the unittest run failing with an import error
Step 1: Claude writes only the tests, runs them, and the run fails as expected.

Notice the words “Do NOT create slugify.py yet”. Without that line, Claude may write the tests and the code in one go, and you never see a red run. Saying it out loud costs nothing.

Is an import error a real failing test?

It counts as red, but it is the weakest kind. Python could not even load the test file, so none of the three tests ran.

That is fine for the very first step. If you want a sharper red, ask Claude to create an empty function that returns nothing, so each test fails on its own line.

Step 2: Write the Smallest Code That Passes (Green)

Next we asked for the smallest possible implementation. The phrase “smallest” keeps Claude from adding features nobody asked for.

Now write the smallest slugify.py that makes the tests pass. Run the tests
again and reply in two short lines.

Claude wrote a six-line file, ran the suite, and all three tests passed. The code lowercases the text, removes punctuation with Python’s string.punctuation table, and joins the words with hyphens.

Claude Code terminal showing slugify.py being written and three unittest tests passing
Step 2: the smallest code that makes every test pass.

This is the moment to read what Claude wrote. Six lines are easy to review. In a real project you would also read the tests, because the tests are now the spec you own.

Step 3: Add a New Rule and Watch It Fail

Now comes the part that makes TDD worth the effort. We added a new rule: hyphens inside words must stay, so “well-known tool” becomes “well-known-tool”. The first version of the code removed every hyphen, so it should break.

New rule: hyphens inside words must stay, so 'well-known tool' becomes
'well-known-tool'. Add that test first, run it to see it fail, then fix
the code and run all tests. Reply in three short lines.

Claude added test_inner_hyphens_kept and ran the suite. The new test failed while the other three still passed, which is exactly the red state we wanted. Then Claude changed one line in slugify.py to stop stripping hyphens and ran everything again.

Claude Code terminal showing the new inner hyphens test failing, then the code being updated and all tests passing
Step 3: the new test fails first, then a one-line fix turns the whole suite green.

Claude’s summary said the test failed with 'wellknown-tool' != 'well-known-tool' because the code was stripping every hyphen. It also warned that leading, trailing or doubled hyphens would now pass through unchanged, and that no test covered them yet. That honest note is a gift: it tells you what to test next.

When a New Test Passes on the First Run

In our first, separate attempt we asked for a different rule: leading and trailing hyphens must be removed. Claude added the test and ran it, and it passed immediately. Claude said so plainly: there was no red step, and it had not changed the code.

Claude Code terminal explaining that the new test passed on the first run so there was no red step
A new test that passes at once did not prove anything new, and Claude said so.

The reason was that the old code already stripped every hyphen, so none could be left at the edges. The test was valid, but it did not describe a behavior we were missing.

That is why you ask Claude to run each new test before fixing anything. If it does not fail, either the rule is already met or the test is checking the wrong thing.

What to do when there is no red step

  • Read the new test and ask whether it can really fail.
  • Try a clearly broken input and see if the test catches it.
  • Keep the test as a guard against future changes, but do not count it as proof of new work.
  • Ask Claude which behavior is still untested.

Step 4: Refactor With Tests as a Safety Net

Refactoring means changing how code is written without changing what it does. Once your tests pass, you can ask Claude to tidy up and trust the suite to catch mistakes.

Refactor slugify.py so it is easy to read. Do not change behavior.
Run all tests when you are done and tell me the result.

We did not run a separate refactor in our demo, because six lines had nothing to tidy. We list the prompt because it is the third stage of the loop and you will need it in bigger files. If a test fails after the refactor, you can roll back with /rewind, which our commands cheat sheet covers.

The Claude Code Test Driven Development Loop at a Glance

Diagram of the test-driven loop with red, green and refactor steps that repeat for each new rule
Each new rule starts a fresh red, green, refactor cycle.

Think of every rule as its own small cycle. You never write more than one failing test at a time, and you never leave the loop with a red suite. That keeps each Claude Code session easy to review and easy to undo.

Make Claude Keep Going Until the Tests Pass

Sometimes the green step takes more than one attempt, especially in real projects. The official docs describe three ways to make Claude keep going until the check passes, and they apply neatly to TDD.

  • In the prompt, ask Claude to run the tests after and keep going until they pass. Claude decides for itself when it is satisfied.
  • As a goal, use the /goal command with a condition such as all tests in a folder passing. A separate model checks the condition after every turn.
  • As a Stop hook, run your test script whenever Claude tries to end its turn, and send it back to work if the script fails.
Official Claude Code best practices page with the goal option for making all tests pass highlighted
The docs show a goal condition that keeps Claude working until all tests pass.

The docs say the goal option matters most for long background runs. For a short TDD loop like ours, a clear prompt was enough. For the hook route, see our guide to Claude Code hooks.

Try It Yourself

Here is a practice task you can run in any empty folder. Create a CLAUDE.md with your test command, start Claude Code, and paste this prompt.

Let's do TDD. Write test_wordcount.py for a function word_count(text) in
wordcount.py. It should count words separated by any whitespace and return 0
for an empty string. Do NOT create wordcount.py yet. Run the tests and show
me they fail. Then wait for my go-ahead before writing any code.

When the red run looks right, say “Now write the smallest code that passes.” Then add one new rule at a time, such as ignoring punctuation or counting hyphenated words as one. Always ask for the failing run before the fix.

Common Mistakes

  • Letting Claude write the tests and the code together, so you never see a red run.
  • Asking for too many rules at once. One rule per cycle keeps failures easy to read.
  • Skipping the review of the tests. Claude can write a test that passes for the wrong reason.
  • Forgetting to put the test command in CLAUDE.md, so Claude picks a different command each time.
  • Treating a test that passed on the first run as proof that new work happened.
  • Letting a long session pile up. Use /clear between unrelated features, as explained in our guide to the context window.

Pro Tips

  • Use plan mode first on bigger features, so Claude lists the test cases before writing any. Our plan mode guide shows how.
  • Ask Claude to reply in two or three short lines, as we did, so the red and green results stay readable on screen.
  • When Claude warns about an untested edge case, copy that warning straight into your next prompt as the new rule.
  • Run the whole suite, not just the new test, after every fix. A fix for one rule can break another.
  • Commit after every green run, so each cycle is a safe checkpoint.

Claude Code TDD Cheat Sheet

Cheat sheet card with the red green refactor cycle, tested prompts, setup tips and things to watch out for
The red, green, refactor cycle and the prompts we tested, on one card.

Frequently Asked Questions

Can Claude Code do test-driven development?

Yes. In our test Claude wrote the failing tests, ran them, wrote the smallest passing code, and fixed a new rule after watching its test fail. It works best when you state the order in the prompt and tell Claude not to write the code early.

How do I stop Claude from writing the code before the tests?

Say it directly in the prompt, for example “Do NOT create slugify.py yet.” In our run Claude followed that instruction and only wrote the test file in the first step.

Which test framework should I use?

Use the one your project already has. We used Python’s built-in unittest because it needs no install, and the test command went into CLAUDE.md. The same workflow applies to any runner Claude can call from the terminal.

What if the new test passes right away?

It means the behavior already worked, or the test is not checking what you think. Ask Claude why it passed, as we did, and look for the rule that is still untested. Keep the test as a guard, but do not count it as new proof.

Do I need to approve every test run?

Not if you pre-approve it. We started Claude Code with accept edits mode and --allowedTools "Bash(python3:*)", so file edits and Python commands ran without prompts while other commands still asked.

Conclusion

Claude Code test-driven development works when you set the order in your prompt: tests first, a visible red run, the smallest passing code, then a refactor. In our demo Claude wrote three tests, turned them green with a six-line file, and fixed a new hyphen rule only after its test failed. Keep the test command in CLAUDE.md, add one rule per cycle, and read the tests yourself. To go deeper on the model behind it all, see our Claude guide, and read the official best practices page for more ways to give Claude a check to run.

Newsletter

New AI tools in your inbox

The best new tools and the AI news that matters, in one short email. Unsubscribe any time.

Free · No spam · Unsubscribe any time

✓ Looks like you’re subscribed

Loading Google’s sign-up form…

Looks like you’re already subscribed

Thanks for reading! New AI tools and the AI news that matters will land in your inbox.

Not subscribed yet? Refresh the page to load the sign-up form.

The sign-up form couldn’t load. If you use an ad or content blocker, allow news.google.com and reload the page.

Free instant check before you pay. Takes a few seconds.

Scroll to Top