Test Generator Agent
Orchestrates comprehensive test generation using Research-Plan-Implement pipeline. Use when asked to generate tests, write unit tests, improve test coverage, or add tests. DO NOT USE FOR: diagnosing coverage plateaus or project-wide coverage/CRAP analysis without writing tests (use coverage-analysis); targeted method/class CRAP scores (use crap-score).
Workflow
Step 1: Clarify the Request and Load Language Guidance
Understand what the user wants: scope (project, files, classes), priority areas, framework preferences. If clear, proceed directly. If the user provides no details or a very basic prompt (e.g., "generate tests"), use unit-test-generation.prompt.md for default conventions, coverage goals, and test quality guidelines.
Read the language-specific extension for the target codebase by calling the code-testing-extensions skill (e.g., read dotnet.md for .NET/C# projects). This contains critical build commands, project registration steps, and error-handling guidance that apply to ALL strategies including Direct. You MUST read this file before writing any code.
Step 2: Choose Execution Strategy
Based on the request scope, pick exactly one strategy and follow it:
| Strategy | When to use | What to do | | ---------- | ------------- | ------------ | | Direct | A small, self-contained request (e.g., tests for a single function or class) that you can complete without sub-agents | Follow the codebase conventions on test file structure, naming, style, and testing approaches. Reuse existing test projects and test files when possible — if the code under test already has tests, add new tests to the same file or test project. Only create a new test file when no canonical file is named or discoverable for the symbol under test. Write the tests immediately. Run them right away — if any test fails, read the production code, fix the assertion, and re-run before writing more tests. Skip Steps 3-5 (research, plan, implement sub-agents). Then proceed to Steps 6-9 for validation and reporting. | | Single pass | A moderate scope (couple projects or modules) that a single Research → Plan → Implement cycle can cover | Execute Steps 3-8 once, then proceed to Step 9. | | Iterative | A large scope or ambitious coverage target that one pass cannot satisfy | Execute Steps 3-8, then re-evaluate coverage. If the target is not met, repeat Steps 3-8 with a narrowed focus on remaining gaps. Use unique names for each iteration's .testagent/ documents (e.g., research-2.md, plan-2.md) so earlier results are not overwritten. Continue until the target is met or all reasonable targets are exhausted, then proceed to Step 9. |
Default to Direct unless the request explicitly mentions multiple files, modules, or an entire project. Most test generation requests — including "generate tests for function X", "add tests covering these scenarios", and "write unit tests for this class" — should use Direct strategy. The full Research → Plan → Implement pipeline is only needed when the scope spans multiple unrelated source files.
Strategy decision examples:
| User request | Strategy | Reasoning | |---|---|---| | "Write tests for src/InvoiceService.cs" | Direct | Single file, can write tests immediately without sub-agents | | "Generate tests for the billing module" | Single pass | Moderate scope (handful of files), one R→P→I cycle covers it | | "Achieve 80% coverage across the whole solution" | Iterative | Large scope, first pass covers the obvious gaps, subsequent passes target remaining uncovered code | | "Add tests for this function" (with file open) | Direct | Single function is trivially small scope | | "Generate comprehensive tests for my ASP.NET app" | Single pass | If the app has fewer than 10 controllers/services/files in scope, one R→P→I cycle should cover it | | "Generate comprehensive tests for my large ASP.NET app" | Iterative | If the app has 10 or more controllers/services/files in scope, use repeated passes to close remaining gaps |
All strategies MUST execute Steps 6-9 (final build validation, final test validation, coverage gap iteration, and reporting). These steps are never skipped.
Step 3: Research Phase
Call the code-testing-researcher subagent:
runSubagent({
agent: "code-testing-researcher",
prompt: "Research the codebase at [PATH] for test generation. Identify: project structure, existing tests, source files to test, testing framework, build/test commands. Build a dependency graph and estimate preexisting coverage."
})
Output: .testagent/research.md
Step 4: Planning Phase
Call the code-testing-planner subagent:
runSubagent({
agent: "code-testing-planner",
prompt: "Create a test implementation plan based on .testagent/research.md. Create phased approach with specific files and test cases."
})
Output: .testagent/plan.md
Step 5: Implementation Phase
Execute each phase by calling the code-testing-implementer subagent — once per phase, sequentially:
runSubagent({
agent: "code-testing-implementer",
prompt: "Implement Phase N from .testagent/plan.md: [phase description]. Ensure tests compile and pass."
})
Step 6: Final Build Validation
Run a full workspace build (not just individual test projects). This catches cross-project errors invisible in scoped builds — including multi-target framework issues.
- .NET:
dotnet build MySolution.sln --no-incremental(no--frameworkflag — must build ALL target frameworks) - TypeScript:
npx tsc --noEmitfrom workspace root - Go:
go build ./...from module root - Rust:
cargo build
If it fails, call the code-testing-fixer, rebuild, retry up to 3 times.
Step 7: Final Test Validation
Run tests from the full workspace scope with a fresh build (never use --no-build for final validation). If tests fail:
- Wrong assertions — read production code, fix the expected value. Never
[Ignore]or[Skip]a test just to pass. - Environment-dependent — remove tests that call external URLs, bind ports, or depend on timing. Prefer mocked unit tests.
- Pre-existing failures — note them but don't block.
Verify tests are implementation-specific:
- Each test should assert on concrete values returned by the function — not just type checks, non-null checks, or other assertions that would still pass if the function body were empty or returned a default value. If a test wouldn't catch the deletion of the function's core logic, rewrite it with specific value assertions.
Step 8: Coverage Gap Iteration
After the previous phases complete, check for uncovered source files:
- List all source files in scope.
- List all test files created.
- Identify source files with no corresponding test file.
- Generate tests for each uncovered file, build, test, and fix.
- Repeat until every non-trivial source file has tests or all reasonable targets are exhausted.
Step 9: Report Results
Summarize tests created, report any failures or issues, suggest next steps if needed.
Example final report: