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

"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:
| Phase | What Codex does | What evidence you inspect |
|---|---|---|
| Red | Writes tests only, without implementation code | Failing test name and failing assertion |
| Green | Makes the smallest implementation change, without editing tests | Passing test output and changed file list |
| Refactor | Cleans up structure and reruns tests | Still 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 signal | How to block it |
|---|---|
| A test file was modified | Inspect 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 added | Grep test files and forbid new skip/only markers |
A matcher was weakened (toBe → toBeTruthy) | 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 relevant | Put 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 layer | When to use it | Command example | Evidence Codex should provide |
|---|---|---|---|
| Unit test | Fast validation for one function | npm run test:unit or vitest run or pytest | Failing test name and assertion |
| Integration test | Verify module interactions | npm run test:integration | Failing module or interface |
| E2E test | Verify a user flow | npx playwright test | Failing scenario and screenshot |
| Type check | Catch compile-time errors | npm run typecheck or tsc --noEmit | Error file and line |
| Lint | Enforce code rules | npm run lint or eslint | Error file and rule name |
| CI | Team-level gate | GitHub Actions | Status 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
- Local tests are green: Codex completes the three phases and provides the evidence package
- Review pane diff check: inspect whether test files were modified
- Create a PR: push to a feature branch
- Required status checks must pass: CI runs the full test suite, typecheck, and lint
- 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:
- Run the test first to reproduce the failure
- Ask Codex to make the smallest fix
- Generate a patch artifact
- 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
Step 1: List the test cases
Ask Codex to list the minimal behavior, boundary cases, and regression scenarios without writing implementation code. - 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
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
Step 4: Refactor after green
Clean up structure only after the tests pass, then rerun the tests. - 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?
How do I make Codex actually run tests?
Can Codex edit tests when tests fail?
Is coverage percentage a quality standard?
How do I verify frontend pages?
When is TDD a poor fit for Codex?
11 min read · Published on: Jul 30, 2026 · Modified on: Jul 30, 2026
OpenAI Codex: CLI, Desktop, Cloud, and Team Workflows
If you landed here from search, the fastest way to build context is to jump to the previous or next post in this same series.
Previous
Codex Skills and Plugins Guide: Turn Team Workflows into Reusable Capabilities
A practical guide to AGENTS.md, Codex Skills, Plugins, MCP, and Subagents: build a minimal code-review Skill, then decide when it should become a role-specific plugin.
Part 10 of 11
Next
This is the latest post in the series so far.



Comments
Sign in with GitHub to leave a comment