Writing Tests First With a Coding Agent
A coding agent can produce an implementation quickly. The harder task is making sure it implements the behavior you intended. Writing tests first gives you an executable agreement: define the result, observe a meaningful failure, and only then ask the agent to change production code.
This walkthrough uses a small checkout calculation. The same workflow applies to API handlers, validation rules, and bug fixes.
§ 1. Establish a working baseline
Start on a clean branch. Ask the agent to inspect the repository, identify the test framework, and run the existing checks before editing anything. Record the commands and any existing failures so you can distinguish new regressions from unrelated problems.
If you use Claude Code, Codex, or Gemini CLI, Vana API can supply model access through the protocol your tool supports. It offers an OpenAI-compatible endpoint at https://api.vanaapi.com and also supports Anthropic Messages and Gemini native protocols. Create a Vana API account if you need access, then configure your tool using its supported provider settings. Keep credentials outside the repository.
§ 2. Write the behavior contract
Before requesting code, describe the feature in observable terms. For this example, a checkout function accepts a subtotal and a discount, both expressed as integer cents.
- Shipping costs 500 cents when the original subtotal is below 5,000 cents.
- Shipping is free when the original subtotal is at least 5,000 cents, regardless of the discount.
- The result is the subtotal minus the discount, plus shipping.
- Both inputs must be nonnegative safe integers, and the discount cannot exceed the subtotal.
- Invalid inputs must raise a validation error.
Ask the agent to identify ambiguities before proceeding. Here, the important distinction is that shipping eligibility uses the original subtotal, not the discounted amount. A precise contract prevents the agent from silently choosing a different rule.
§ 3. Request tests without implementation
Give the agent a bounded task: “Add tests for this contract using the existing test framework. Do not change production code. Use explicit expected values rather than reproducing the calculation inside the tests.”
Review the proposed cases yourself. Useful examples include:
- A subtotal of 4,000 and discount of 500 returns 4,000.
- A subtotal of 4,999 and no discount returns 5,499.
- A subtotal of 5,000 and discount of 1,000 returns 4,000.
- A subtotal of zero and no discount returns 500 under the stated contract.
- Negative, fractional, unsafe-integer, and excessive-discount inputs raise a validation error.
The zero-subtotal case may look surprising. That is useful: if the business wants empty checkouts rejected instead, revise the contract and test before implementation.
§ 4. Verify a meaningful red result
Run the focused test file. Confirm that the new tests fail because the behavior is missing or incorrect, not because the test runner is misconfigured.
If the function does not exist yet, a missing-export failure can establish the initial red state. Where useful, add only the minimum interface scaffold, then run again to expose failing assertions. Do not mistake a broken import path or unavailable dependency for evidence that the tests exercise the requirement.
§ 5. Ask for the smallest passing implementation
Now instruct the agent: “Implement the agreed behavior with the smallest reasonable production change. Do not weaken assertions, skip tests, or add unrelated dependencies. If a test appears wrong, explain the conflict before editing it.”
Run the focused tests after the change. Inspect the diff, especially input validation and the shipping threshold. Passing tests are evidence of the examples covered, not proof that every possible input is correct.
§ 6. Refactor while preserving behavior
Once the tests pass, ask for a separate cleanup pass only if it improves clarity. Keep the public contract unchanged and rerun the focused tests after each meaningful edit.
Then run the broader suite, lint checks, and type checks available in the repository. A correct checkout function can still break a caller through a changed signature or error convention.
§ 7. Review the evidence before merging
Request a final summary containing changed files, commands actually run, results, and any checks that could not run. Verify that summary against the tool output and review the complete diff yourself.
The repeatable loop is simple: agree on behavior, write tests, observe failure, implement, and verify. The agent handles much of the editing; you remain responsible for deciding whether the tests describe the right product.