Toggle Theme

Codex Test-Driven Development: Make AI Write the Test First, Then Get to Green

Easton editorial illustration: Codex project workflow bench

"OpenAI Codex best practices recommend stating the Goal, Context, Constraints, and Done when, and using tests, checks, and review as completion criteria."

You see Codex print “all tests passed” in the terminal, but the message contains only the conclusion. It does not show the command, and it does not say which tests ran. Then you open the diff and notice that the test file changed too: an assertion went from toEqual(42) to toBeTruthy(). The problem is not trusting Codex. The problem is trusting a “green” result with no evidence. This guide gives you a repeatable prompt pattern, an evidence checklist, and false-green guardrails so “trust the AI” becomes “check reproducible proof.”

Why Test-First Work Matters More with Codex

Test-first work is not only “write tests before code.” With Codex, tests become executable acceptance criteria. Codex can run commands, read output, and edit files, but you still need to define what “done” means before it starts.

OpenAI Codex documentation says Codex tends to produce better work when it can verify the result. That means if you tell Codex how to verify the change, which command to run, and what result you expect, it has a better chance of making the right edit. Vague tasks get vague treatment. Smaller tasks are easier to test and review.

The red-green-refactor loop has three phases:

PhaseWhat Codex doesWhat evidence you inspect
RedWrites tests only, without implementation codeFailing test name and failing assertion
GreenMakes the smallest implementation change, without editing testsPassing test output and changed file list
RefactorCleans up structure and reruns testsStill green, and the diff does not include test files

Do not skip these steps. If you skip red, you do not know whether the test really catches the new behavior. If you skip refactor, you may leave behind patched-together code. For the broader Codex basics, start with the complete Codex beginner guide.

Red Phase: Make Codex Write a Test That Can Fail

The red phase is mostly about constraints: modify only test files and do not write implementation code. Ask Codex to list the test cases first, generate them one by one, and finally run the tests to confirm the red state.

Prompt Template

Only modify test files. Do not modify implementation code.
Write tests for [feature name] covering:
1. [minimal behavior]
2. [boundary case]
3. [error path]
Afterward, run `npm test` and paste the failing test name and assertion.

This prompt must include “do not modify implementation code.” Without that line, Codex may quietly implement the behavior while writing the test, which destroys the red verification step.

Confirm the Red State

After Codex finishes, ask for the complete test output. The red state should fail on the expected assertion, not on a compile error or import failure. If you see this:

FAIL src/utils/calculator.test.ts > add > should handle negative numbers
AssertionError: expected -1 to be 42

the test is checking behavior for negative input and failing in the expected place. If you only see TypeError: Cannot find module 'calculator', the red state is a compile error, not a useful test failure.

Sort the Test List

Do not ask Codex to generate dozens of tests in one pass. Start with the minimal behavior, boundary cases, regression bugs, and error paths, then move forward one case at a time. You can keep the test list in AGENTS.md or a separate document so Codex can follow it case by case.

For unit testing fundamentals, see Vitest Unit Testing and TDD and the Vitest practice guide.

Green Phase: Make the Smallest Change Until Tests Pass

The hard guardrail in the green phase is simple: test files are off limits. If tests fail, Codex may change implementation code only. It must not change the tests to fit the implementation.

Prompt Template

Only modify implementation files. Do not modify test files.
Make the smallest change needed for the tests to pass.
Afterward, run `npm test` and paste the passing summary.

This prompt must include “do not modify test files.” Without it, Codex may edit assertions, delete tests, or skip cases to make the run appear green.

Check the Passing Summary and the Diff

After Codex finishes, ask for the test count, pass count, and duration:

PASS src/utils/calculator.test.ts (1.2s)
  add
    ✓ should add two numbers (5ms)
    ✓ should handle negative numbers (3ms)
  2 tests passed

Then inspect the diff. If a test file appears in the changed file list, reject that green phase.

False-Green Guardrails

False green is the biggest TDD risk. Watch for these six signals:

False-green signalHow to block it
A test file was modifiedInspect the diff and reject any green phase that includes test files
An assertion changed from toEqual(42) to toBeTruthy()Ask Codex to show the full assertion and compare it manually
New test.skip() / test.only() was addedGrep test files and forbid new skip/only markers
A matcher was weakened (toBetoBeTruthy)Compare the test diff and forbid weaker matchers
A fixture was changed into the “correct answer”Inspect fixture diffs and forbid changes to input data
Only unit tests ran, while integration tests were relevantPut all relevant test commands in Done when

Codex does not enforce these guardrails for you. You need to check them during review. Teams with more automation can move some of these checks into CI or a pre-commit hook.

Refactor Phase: Clean Up Only After Green

The refactor phase starts only after the tests are green. If tests are not passing, do not refactor. After refactoring, rerun the tests; do not rely on the diff alone.

Prompt Template

All tests are passing. Now refactor only:
- Rename variables to make intent clearer
- Remove duplicated code
- Extract functions
Do not modify test files. Afterward, rerun `npm test`.

In this phase, Codex changes structure, not behavior. If the refactor introduces new logic, it is not a refactor anymore; it is a new green phase for a new behavior.

Rerun Tests to Verify

After refactoring, Codex must run the same test set again. If the tests stay green, the refactor did not break existing behavior. If a test fails, the refactor changed behavior and needs to be reverted or fixed.

Check the diff: test files should not appear in the changed file list. If they do, the refactor crossed the boundary.

For a refactoring example, see AI Refactoring with a Test Safety Net.

Evidence Package: Make Codex Hand Over Reviewable Proof

Before each phase ends, Codex should hand over this evidence:

Pre-Completion Acceptance Checklist

  • Test command and exit code
  • Failing or passing summary
  • Changed file list
  • Whether test files were modified
  • CI status checks, if available

Completion Response Template

Ask Codex to respond in this format:

### Test results
- Command: `npm test`
- Exit code: 0
- Passed: 42 tests
- Failed: 0
- Duration: 1.2s

### Changed files
- src/utils/calculator.ts
- (test files were not modified)

### Remaining risk
- Boundary case not covered: negative input

This format makes the evidence readable, comparable, and easy to archive. If Codex only says “tests passed,” you cannot tell whether it actually ran the tests, changed test files, or missed a boundary case.

Test Layer Choices and Command Examples

Different test layers fit different verification jobs. Do not jump straight to full E2E, and do not rely only on snapshot tests.

Test Layer Decision Table

Test layerWhen to use itCommand exampleEvidence Codex should provide
Unit testFast validation for one functionnpm run test:unit or vitest run or pytestFailing test name and assertion
Integration testVerify module interactionsnpm run test:integrationFailing module or interface
E2E testVerify a user flownpx playwright testFailing scenario and screenshot
Type checkCatch compile-time errorsnpm run typecheck or tsc --noEmitError file and line
LintEnforce code rulesnpm run lint or eslintError file and rule name
CITeam-level gateGitHub ActionsStatus checks page

Treat these commands as examples to replace with your project’s real commands. Projects differ: Jest, Vitest, Pytest, Playwright, GitHub Actions. For more testing background, see the Next.js Jest testing guide.

Unit tests are usually the best first verification layer for Codex. They run quickly, produce clear failure messages, and are easy to document in AGENTS.md. Integration and E2E tests are better for module interactions and user flows, but failures are harder to diagnose. Type checks and lint are useful secondary checks for compile errors and code style. CI is the final team gate: after all local tests are green, required CI status checks still need to pass before merge.

Freeze TDD Rules in AGENTS.md and Prompts

Put the TDD rules in AGENTS.md so Codex reads them before each task. That saves you from repeating the same prompt every time.

Small AGENTS.md Example

Place something like this at the project root or in a local directory:

## Test commands
- Run tests: `npm test`
- Run unit tests: `npm run test:unit`
- Run typecheck: `npm run typecheck`

## TDD rules
- Red phase: only modify test files
- Green phase: only modify implementation files
- Refactor phase: must re-run tests after cleanup

## Done when
- All tests pass
- Test files are not modified in green/refactor phase
- Diff contains only expected changes

This file tells Codex which test commands exist, what each phase is allowed to change, and what counts as done. For more AGENTS.md guidance, see the Codex project rules article in this series.

Local directories can carry more specific rules. For example, src/utils/AGENTS.md can list test scenarios, boundary cases, and known bugs for src/utils/.

Do not put secrets, tokens, or sensitive configuration in AGENTS.md. Codex will read this file, but it will not automatically filter sensitive values.

From Local Green to Team CI Gates

Local green tests do not mean the change is mergeable. In a team workflow, CI gates matter: required status checks must pass, and PR review must be complete.

Workflow Checklist

  1. Local tests are green: Codex completes the three phases and provides the evidence package
  2. Review pane diff check: inspect whether test files were modified
  3. Create a PR: push to a feature branch
  4. Required status checks must pass: CI runs the full test suite, typecheck, and lint
  5. Human review: inspect the diff, evidence package, and remaining risks

Green Tests Do Not Mean Automatic Merge

GitHub Docs state that required status checks must pass before a protected branch can be merged into. There is one risk: a skipped job reports success and does not block PR merge, even if it is a required check. That means a PR may be mergeable even though some checks did not actually run.

To prevent false green from skipped workflows, open the GitHub Checks page and confirm that every required check actually ran, rather than being skipped.

Using the Review Pane

The Codex app review pane lets you inspect whether the diff includes test-file changes. You can stage, unstage, or revert by file or hunk. If a test file was modified, revert that test-file change and keep only the implementation change.

For more CI background, see GitHub Actions CI and GitHub Actions workflow basics. For PR review workflow, see the Codex AI code review article in this series.

Boundaries for Automatic CI Failure Fixes

codex exec and the Codex GitHub Action can help with failing CI tests, but they need safety boundaries.

Automatic Failure-Fix Flow

According to the Codex non-interactive documentation, a CI failure-fix flow looks like this:

  1. Run the test first to reproduce the failure
  2. Ask Codex to make the smallest fix
  3. Generate a patch artifact
  4. Open a PR that separates the fix from the original job

You can pipe test output into Codex with npm test 2>&1 | codex exec "summarize the failure and suggest the smallest fix" so it can summarize the failure and propose a minimal repair.

Safety Principles

Do not give Codex write access to the repository and access to secrets in the same job. Use the smallest practical sandbox: read-only by default, workspace-write only for the working directory, and danger-full-access only in controlled environments.

Separate patch artifact generation from PR creation so API keys are not exposed to untrusted code.

Do not expand this into a full GitHub Actions YAML here. Keep the principle simple: least privilege, separated patches, and human merge. For more automation detail, see the codex exec automation article in this series.

Summary

Codex test-driven development comes down to a three-phase operating pattern: red writes tests only, green changes implementation only, and refactor cleans up after rerunning tests. Each phase must produce reviewable evidence: the command, the failing or passing summary, and the changed file list.

The false-green guardrails are the real difference: check whether test files changed, whether assertions were weakened, whether tests were skipped, whether fixtures changed, whether only unit tests ran when integration tests mattered, and whether the CI workflow was skipped.

For teams, local green tests are not enough. CI status checks, PR review, and protected-branch rules still decide whether the change can be merged.

The next time you ask Codex to change code, ask it to write the test first, confirm red, and then inspect the evidence. Do not stop at the words “tests passed.”

Run one TDD cycle with Codex

Split the work into red, green, and refactor rounds: ask Codex to write a failing test first, make the smallest implementation change, and then verify with test output, diff review, and CI.

  1. 1

    Step 1: List the test cases

    Ask Codex to list the minimal behavior, boundary cases, and regression scenarios without writing implementation code.
  2. 2

    Step 2: Write the failing test

    Ask Codex to modify only test files and run the relevant test command to confirm the red state.
  3. 3

    Step 3: Make the smallest implementation change

    Ask Codex to keep test assertions unchanged, modify only implementation code, and run the same tests again.
  4. 4

    Step 4: Refactor after green

    Clean up structure only after the tests pass, then rerun the tests.
  5. 5

    Step 5: Inspect evidence and diff

    Review the command output, test-file changes, review pane or PR diff, and CI status checks.

FAQ

Can Codex write unit tests?
Yes. Codex can generate test code, but you still need to review whether the red test fails on the expected assertion and whether it covers boundary cases.
How do I make Codex actually run tests?
Put the test command and required output in Done when. You can also pipe output into Codex with `npm test 2>&1 | codex exec "summarize the failure and suggest the smallest fix"`.
Can Codex edit tests when tests fail?
In the green phase, no. If a test fails, ask Codex to summarize the failure first, then make the smallest implementation fix.
Is coverage percentage a quality standard?
Coverage is a signal, not a standard. High coverage does not prove the tests are useful; the assertions may still be checking the wrong behavior.
How do I verify frontend pages?
Use Playwright or browser tests. Codex can run `npx playwright test` and include the failing scenario and screenshots in the evidence.
When is TDD a poor fit for Codex?
Exploratory prototypes, one-off scripts, and projects without a stable test framework are poor fits for strict TDD. In those cases, it is usually better to change the code first and add tests afterward.

11 min read · Published on: Jul 30, 2026 · Modified on: Jul 30, 2026

Comments

Sign in with GitHub to leave a comment

Easton BlogEaston Blog