Generate tests that catch bugs
Test and debug with Claude Code
Testing and debugging with Claude Code works when the tests, not the model, decide what “done” means: the test commands live in CLAUDE.md, hooks rerun the suite after every edit, the implementing session cannot edit the test files, and every bug fix starts with a test that fails for the diagnosed reason. Plan mode keeps diagnosis read-only.
This hub is for developers who let Claude Code write tests and fixes, and for tech leads who decide what those pull requests must prove. The familiar failure: Claude reports “all tests pass”, coverage goes up, and the bug ships anyway, because the new tests asserted that mocks were called or an assertion was quietly loosened. Commands were checked against Claude Code v2.1.283 (latest channel).
Which Claude Code test page answers your question?
Section titled “Which Claude Code test page answers your question?”| Your question | Page |
|---|---|
| How do I get tests that follow our patterns, run red-green-refactor, and catch real bugs? | Test generation and TDD with Claude Code |
| Something is broken. How do I find the root cause instead of patching the symptom? | Debugging with Claude Code in the terminal |
| How strong does a suite have to be before I trust tests I did not read? | How strong is your oracle? |
| How do I stop the agent from editing the checks that judge it? | Protecting the oracle |
| Claude Code itself misbehaves: hangs, permission loops, lost context | Troubleshooting Claude Code |
Testing practice that is the same in every agent is in testing workflows for every tool.
In what order should you set up testing with Claude Code?
Section titled “In what order should you set up testing with Claude Code?”Each step removes one way for a green result to lie. Do them once per repository.
-
Write the test commands into
CLAUDE.md. Name the command for one file, for related tests and for the full suite, plus the rule “never edit a test to make it pass”. Claude uses these instead of guessing. -
Add the feedback hooks. A
PostToolUsehook onEdit|Writeruns the related tests after each edit, and aStophook runs the fast suite before Claude reports done. Both exit with code 2 on failure, which sends the hook’s stderr back to Claude, so redirect the runner’s output with1>&2. The scripts and settings block are in test generation and TDD; other events are in hooks automation. -
Lock the tests while Claude implements. “Do not edit the test” in a prompt is a request. A deny rule such as
"Edit(**/*.test.ts)"inpermissions.deny(orclaude --disallowedTools "Edit(**/*.test.ts)") blocks the file tools and recognized shell writes such assedand>, but not a script that opens files itself. A CI check outside the diff is the lock for the branch. -
Diagnose read-only. From v2.1.283 (the
latestchannel), interactive sessions usually start in auto mode, where a classifier approves actions instead of you;claude -pand some providers’ default models still start in Manual. For a bug, switch to plan mode (claude --permission-mode plan,/plan, orShift+Tab) so nothing changes until Claude names one cause as file, line and condition. -
Prove before fixing. A new test must fail for the diagnosed reason before any fix is written. If it fails for a different reason, the diagnosis is wrong.
How do you know Claude Code’s tests and fixes are right without reading every line?
Section titled “How do you know Claude Code’s tests and fixes are right without reading every line?”Read the evidence and open the diff only where the evidence points.
| Evidence | What it proves | Owner |
|---|---|---|
| A list of test names approved before generation | The suite covers the behaviours you care about | Developer |
| The new test ran red, for the stated reason, before the fix | The test detects the bug it claims to | Developer (from hook output) |
| Test files unchanged in the fix’s diff | Nobody passed the suite by weakening it | CI check on test paths |
| Mutation survivors listed and triaged | The suite catches injected bugs, not only today’s code | Reviewer |
| Full suite, types and lint green in CI | Existing behaviour still holds, outside the agent’s control | CI |
What a pull request attaches as proof is defined in the evidence bundle, and why you read evidence instead of the diff is argued in reading evidence instead of code. The fix-by-test habit behind this table is in test-driven fixing.
What goes wrong when Claude Code tests and debugs its own work?
Section titled “What goes wrong when Claude Code tests and debugs its own work?”| Symptom | Cause | Recovery |
|---|---|---|
| Suite green, bug in production | Tests assert mocks, not behaviour | Add an integration test at the seam; run the mutation prompt above |
| A fix passes by changing an assertion | Test files were editable during the fix | Add the permissions.deny rule and a CI check that fails when test paths change without an owner’s approval |
| The same crash returns from another caller | Claude patched the symptom with a null check | Return to plan mode; ask where the bad value is produced and which callers share the assumption |
| Turns end slowly, or Claude loops on a red suite | The Stop hook runs a slow or flaky suite | Point it at the fast unit tests; leave slow suites to CI |
| Snapshot files change in a fix although tests are denied | vitest -u or a script rewrote them; deny rules do not cover subprocesses that open files themselves | Revert the snapshots, add "Bash(npx vitest * -u*)" and "Bash(npx vitest * --update*)" to permissions.deny (other spellings, such as pnpm vitest or npm test -- -u, need their own rules), and make the CI test-path check include __snapshots__/, which is the real lock |
| The diagnosis sounds right but the new test fails differently | Two plausible causes were never separated | Treat the diagnosis as disproved; ask Claude for the evidence that rules each cause out |
Where to go next with testing and debugging in Claude Code
Section titled “Where to go next with testing and debugging in Claude Code”Find the root cause
Ship what the tests proved
Testing skills and plugins
The code under test comes from building with Claude Code. Using another agent as well? The same stage is covered in test and debug with Codex and test and debug with Cursor.