Run Relevant Tests
Scopes test runs to changed behavior while requiring relevant coverage before completion.
Scenario
You work in a growing TypeScript application with hundreds of tests.
Running the entire suite takes several minutes.
During development, the team expects engineers to run tests relevant to the code they changed, then use broader validation when the risk or scope justifies it.
You want the coding agent to avoid two bad extremes:
Run no tests
and:
Run the entire repository test suite after every tiny edit
Repository Structure
commerce-api/
├── src/
│ ├── users/
│ ├── orders/
│ ├── payments/
│ └── notifications/
├── tests/
│ ├── users/
│ ├── orders/
│ ├── payments/
│ └── notifications/
├── package.json
└── AGENTS.md
Example scripts:
{
"scripts": {
"test": "vitest run",
"test:users": "vitest run tests/users",
"test:orders": "vitest run tests/orders",
"test:payments": "vitest run tests/payments"
}
}
AGENTS.md
# Project Instructions
## Testing
- Run tests relevant to the behavior you changed.
- When changing a feature, start with that feature's tests.
- Add or update tests when behavior changes.
- Add a regression test when fixing a reproducible bug.
Run the broader test suite when:
- shared code changes;
- multiple features are affected;
- the change modifies a cross-cutting dependency;
- targeted tests do not provide sufficient confidence.
## Completion
Before completing a task:
- run relevant tests;
- run `pnpm lint`;
- run `pnpm typecheck`.
For broad or cross-cutting changes, also run `pnpm test`.
What This Does
This gives the agent a risk-based testing workflow.
For a change limited to:
src/orders/
the agent can begin with:
pnpm test:orders
or the equivalent targeted Vitest command used by the repository.
If the change instead modifies:
src/shared/
and several features depend on that code, broader testing becomes appropriate.
The key idea is:
Test the affected behavior first, then expand validation when the impact of the change expands.
What This Does NOT Do
The instruction does not say:
- Always run every test after every change.
That can waste time in large repositories and may discourage useful incremental validation.
It also does not say:
- Only run the test file you changed.
That can be too narrow.
A production change may affect behavior outside the file that was directly modified.
The correct scope depends on behavior and dependencies, not merely filenames.
Why These Instructions Matter
Suppose an agent changes:
src/orders/calculate-total.ts
A sensible first validation step is the orders test suite.
Now suppose the implementation requires changing:
src/shared/money.ts
and that utility is also used by:
payments
refunds
invoices
The risk has changed.
Running only the orders tests may no longer be sufficient.
This is why the instruction says:
Run the broader test suite when:
- shared code changes;
- multiple features are affected;
- the change modifies a cross-cutting dependency.
The test strategy follows the impact of the modification.
Key Decisions
Test behavior, not files
A changed file is only a clue.
The more useful question is:
What behavior could this change affect?
That determines which tests matter.
Start narrow when appropriate
Targeted tests provide fast feedback.
They are particularly useful during implementation.
Expand when the blast radius grows
Shared utilities, configuration, schemas, and infrastructure can affect many areas.
Broader validation is justified when the change has a broader dependency surface.
Bug fixes should prevent recurrence
If a bug can be reproduced, capture that behavior in a regression test when practical.
The test should fail before the fix and pass after it.
When to Use This Pattern
Use this pattern when:
- the repository has a meaningful test suite;
- full test execution is relatively expensive;
- features have identifiable tests;
- shared code can affect multiple areas;
- developers need fast feedback without sacrificing confidence.
This pattern becomes increasingly useful as repositories and test suites grow.