MyRelay

← Back to the notebook

Write Tests for Existing Code with Claude Code

Writing tests for an existing codebase starts with understanding what the code already promises. Claude Code can help inspect implementation details, identify missing cases, and draft tests, but it still needs boundaries. This walkthrough uses a shipping fee calculator as an example and keeps each task small enough to review without spending an afternoon or an open-ended API budget.

Choose one behavior and record the baseline

Start with a function or module that has clear inputs and outputs. A shipping calculator is a better first target than an entire checkout flow because its dependencies and expected results are easier to inspect. Pick something you understand well enough to challenge an incorrect test.

Before asking Claude Code to edit anything, run the relevant existing tests and record whether they pass. If tests already fail, note those failures separately. Work on a clean branch or otherwise preserve your starting state so you can distinguish generated changes from earlier work.

Ask Claude Code to inspect before it edits

Open Claude Code in the project and give it a narrow discovery task. Ask it to inspect the shipping calculator, nearby tests, and the project's testing instructions. Request a short summary of the test framework, existing conventions, dependencies, and likely gaps. Explicitly say not to change anything yet.

A useful request is: “Inspect the shipping fee calculator and its existing tests. Explain the current behavior and suggest five valuable test cases. Do not edit production code, add dependencies, or read secrets.” Review permission requests rather than granting broad access automatically.

Separate documented rules from implementation guesses

Compare the proposed cases with documentation, existing tests, and any requirements you have. Suppose the documented rule gives free shipping when the discounted subtotal reaches a threshold. Tests should check a subtotal below that threshold, exactly at it, and above it.

If the implementation appears to use the subtotal before discounts instead, do not let Claude silently turn that behavior into the expected result. Ask it to flag the disagreement. An existing codebase may need characterization tests that preserve current behavior, but those should be clearly distinguished from tests of intended requirements.

Generate a small batch using existing conventions

Approve three to five cases and ask Claude Code to implement only those. Tell it to reuse the existing test framework and fixture style, keep production code unchanged, and avoid unrelated cleanup. Small batches make mistakes easier to spot and reduce repeated analysis.

For the shipping example, begin with the threshold cases and one documented discount scenario. Add invalid-input cases only when the expected response is defined. Ask for readable names that describe observable behavior, rather than names tied to internal helper calls.

Run the focused tests and investigate failures

Have Claude Code run the smallest relevant test group first, using the project's established runner. If it cannot execute tests in the current environment, ask it to say so explicitly. Generated tests are not verified tests.

When a test fails, ask for a diagnosis before allowing another edit. The cause might be an incorrect expectation, an incomplete fixture, an environment issue, or a real defect. Do not accept a changed assertion merely because it makes the suite green. Handle confirmed production defects as a separate, reviewable change.

Check whether the assertions catch a regression

Read the diff yourself. Check that expected values follow the requirement independently, rather than reproducing the calculator's formula. Avoid mocking the calculator itself; isolate only dependencies that genuinely need control.

Then deliberately introduce a small, temporary mistake, such as changing whether the threshold includes equality. The relevant test should fail. Restore the implementation immediately afterward, confirm the focused tests pass again, and run the broader suite. This check does not prove completeness, but it shows whether an important assertion is meaningful.

Review spending before expanding coverage

MyRelay gives an individual developer one key and one pay-as-you-go budget across supported models, and works with Claude Code. Its per-request token and cost records help you see what the walkthrough actually consumed. Create a MyRelay account if you want that shared budget and visibility.

Review costs after the first batch before expanding scope. Keep prompts focused, avoid repeatedly requesting a whole-repository analysis, and finish with a summary of changes, test results, and unresolved assumptions. The useful outcome is a small set of trustworthy regression checks, not simply more generated tests.

More to read