Claude Cursor GitHub Copilot Skill

code-testing-agent

Generate or add unit tests for existing code, from one function to a complete project-wide suite. ALWAYS USE when asked to "write unit tests", "add tests", "generate tests", "cover this untested method", scaffold tests where none exist, or create comprehensive tests across multip

LLM Mart · 0 points · 22 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download dotnet-skills-plugins_dotnet-test_skills_code-testing-agent-8a5a42d.zip · 11 KB
Part of dotnet/skills — 119 skills

Install

skills CLI npx skills add https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/code-testing-agent
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install dotnet-skills@llmmart
Git git clone https://github.com/dotnet/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole dotnet/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Code Testing Generation Skill

An AI-powered skill that generates comprehensive, workable unit tests for any programming language using a coordinated multi-agent pipeline.

Non-negotiable execution contract

Classify scope before editing:

  • Broad (a project/package-wide suite, or multiple production files/modules): create research.md and plan.md in a resolved non-stageable <TESTAGENT_DIR> before implementation, then status.md there after the final test-quality review. If these files are absent, the broad workflow is incomplete.
  • Focused (the user explicitly limits work to one function/class/file or one missing method): do not create intermediate state files or fan out to multiple agents. A sparse project-wide request remains broad even when only one source module is present.

For either scope, run the narrowest relevant test command to a clean exit and finish with a compact Requirement | Evidence table. Each requested behavior must cite an exact test name; validation rows cite the successful command. For focused work, "no intermediate state files" changes only the process, not the final evidence contract.

Intermediate state files are internal working data, never deliverables. Keep <TESTAGENT_DIR> non-stageable, never place it or its files in version-controlled workspace content, and never modify .gitignore to hide them.

Treat completeness as a requirement matrix, not a test-count target. Give every independently requested state, boundary, error path, or interaction its own concrete assertion. Combine cases only when one execution genuinely proves the whole requested combination; do not let a parameterized happy-path case stand in for an empty state, invalid discriminator, or before/at/after boundary. For broad requests that name several production modules or layers, give each named module direct tests for its non-trivial public behavior. Cross-module tests prove composition, but do not substitute for the requested module-level coverage. Judge breadth by the behavior matrix, never by matching or exceeding a raw test count.

For a broad or comprehensive request, the explicit matrix is the floor, not the ceiling. After satisfying it, inspect each target API for observable equivalence partitions and invariants that the prompt did not name: identity, empty, singleton and representative interior inputs; exact boundaries plus an immediately adjacent value; invalid partitions; and ordering, monotonicity, rollover, capacity, truncation, or state invariants implied by the implementation. Add one mutation-relevant case per distinct partition not already proved, using parameterized or table-driven cases for siblings. Stop when remaining inputs exercise the same branch and invariant, not merely when the explicit checklist is complete; never add cases only to raise the count.

When to Use This Skill

Use this skill when you need to:

  • Generate unit tests for an entire project or specific files
  • Improve test coverage for existing codebases
  • Create test files that follow project conventions
  • Write tests that actually compile and pass
  • Add tests for new features or untested code
  • Generate or extend MSTest suites; load writing-mstest-tests as supporting guidance after this entry skill has established scope and project conventions

When Not to Use

  • Running or executing existing tests (use the run-tests skill)
  • Migrating between test frameworks (use migration skills)
  • Answering an MSTest API/pattern or modernization question that does not ask to generate tests (use writing-mstest-tests)
  • Debugging failing test logic

How It Works

This skill coordinates multiple specialized agents in a Research → Plan → Implement pipeline:

Pipeline Overview

┌─────────────────────────────────────────────────────────────┐
│                     TEST GENERATOR                          │
│  Coordinates the full pipeline and manages state            │
└─────────────────────┬───────────────────────────────────────┘
                      │
        ┌─────────────┼─────────────┐
        ▼             ▼             ▼
┌───────────┐  ┌───────────┐  ┌───────────────┐
│ RESEARCHER│  │  PLANNER  │  │  IMPLEMENTER  │
│           │  │           │  │               │
│ Analyzes  │  │ Creates   │  │ Writes tests  │
│ codebase  │→ │ phased    │→ │ per phase     │
│           │  │ plan      │  │               │
└───────────┘  └───────────┘  └───────┬───────┘
                                      │
                    ┌─────────┬───────┼───────────┐
                    ▼         ▼       ▼           ▼
              ┌─────────┐ ┌───────┐ ┌───────┐ ┌───────┐
              │ BUILDER │ │TESTER │ │ FIXER │ │LINTER │
              │         │ │       │ │       │ │       │
              │ Compiles│ │ Runs  │ │ Fixes │ │Formats│
              │ code    │ │ tests │ │ errors│ │ code  │
              └─────────┘ └───────┘ └───────┘ └───────┘

Step-by-Step Instructions

Step 1: Determine the user request

Make sure you understand what user is asking and for what scope. When the user does not express strong requirements for test style, coverage goals, or conventions, source the guidelines from unit-test-generation.prompt.md. This prompt provides best practices for discovering conventions, parameterization strategies, coverage goals (aim for 80%), and language-specific patterns.

Step 2: Size the request before invoking anything

Match the machinery to the scope. Running the full pipeline on a one-file request costs turns and tool calls without improving the tests.

Scope What it looks like How to run it
Focused One function, class, or file; "tests for X only"; extending an existing suite with the missing cases Skip intermediate state files and the sub-agent fan-out. Keep the requirement checklist in your head (or in the final table), read only the target and one neighbouring test for conventions, write the tests, run the narrowest test command, review your own assertions inline.
Broad A project, package, or module set; "comprehensive suite"; a coverage threshold to clear across several files Run the full Research → Plan → Implement pipeline in Step 3, with intermediate state files under <TESTAGENT_DIR> and the completion contract below.

When in doubt, start focused and escalate only if the request turns out to span several files. Escalating costs one extra pass; running the broad pipeline on a focused request costs several.

Before ending a focused request, check all three conditions together:

  1. every named behavior has a concrete assertion, including each requested boundary or error path;
  2. the narrow test command exited successfully;
  3. the final Requirement | Evidence table maps those behaviors to exact test names and cites that successful command.

Do not replace this table with a prose list of covered areas, even for a single-function request.

Step 3: Invoke the Test Generator (broad scope)

Start by calling the code-testing-generator agent with your test generation request:

Generate unit tests for [path or description of what to test], following the [unit-test-generation.prompt.md](unit-test-generation.prompt.md) guidelines. Treat the current workspace as authoritative even when it is sparse, gutted-looking, synthetic, or missing tracked files; never restore or reconstruct it, including with `git checkout`, `git restore`, `git reset`, or `git clean`.

The Test Generator will manage the entire pipeline automatically.

If code-testing-generator is unavailable, do not skip the workflow. Execute the same Research → Plan → Implement sequence inline, resolve <TESTAGENT_DIR> as described below, create the intermediate state files there, and apply the same completion contract.

For broad scope, resolve one absolute <TESTAGENT_DIR> before creating intermediate state files:

  1. Prefer a host-provided session artifact or scratch directory.
  2. Otherwise, in a Git worktree run git rev-parse --path-format=absolute --git-path testagent; this returns a path in worktree-specific Git metadata that cannot be staged.
  3. Outside Git, create a unique directory under the operating system's temporary directory.

Pass the absolute directory to every pipeline agent. The path may be inside the repository's .git metadata directory, but it must not be version-controlled workspace content, appear in git status, or be stageable.

Step 4: Execute with bounded context

For multi-file requests:

  1. Turn every explicit user requirement into a checklist before implementation. Include requested layers, collaborators to mock, boundary cases, integrations, coverage thresholds, and report artifacts. Copy multi-condition requirements verbatim — they must each map to one test that exercises the whole combination.
  2. Research only the requested module or project and write the checklist plus a compact target inventory to <TESTAGENT_DIR>/research.md.
  3. Reuse manifests, symbol references, and deterministic pairing tools instead of reading every source and test file.
  4. For multi-file scopes in C#, Python, TypeScript/JavaScript, Go, Java, Rust, Ruby, Kotlin, Swift, PowerShell, or C++, run find-untested-sources once and consume its pairing and suggested-path output; do not repeat that discovery manually.
  5. Plan each target file once, then implement phases sequentially. Map every checklist item to at least one concrete test or explain why it is blocked.
  6. Build and test the narrow target during fix cycles; run workspace-level validation once at the end.
  7. Before reporting success, re-open the generated tests and verify every checklist item against concrete test names and assertions. Coverage alone is not evidence that a requested mock seam, boundary, state transition, or property combination was tested.
  8. Read a language example from code-testing-extensions only when the repository has no representative tests and the base extension is insufficient.
  9. For .NET, classify SDK-style vs. classic non-SDK before choosing commands or creating files. In classic projects, preserve packages.config, existing framework/mock versions and custom base fixtures, add every new test file to the project's explicit <Compile Include> items, and use the repository's MSBuild/test-runner commands. Never modernize the project or dependency stack merely to generate tests.
  10. For MSTest, inspect the pinned package version before choosing exception assertions. MSTest 3.5.x uses Assert.ThrowsException<T>; do not substitute [ExpectedException], Assert.Throws<T>, or Assert.ThrowsExactly<T>.

Completion contract

Every scope must satisfy points 3–5 below. Points 1 and 2 are the broad-scope artifacts: on a focused request the same reasoning happens inline and no intermediate state files are written.

Do not report completion until all of these are true:

  1. (broad scope) <TESTAGENT_DIR>/research.md records the bounded target inventory, existing test conventions, and the acceptance checklist.
  2. (broad scope) <TESTAGENT_DIR>/plan.md maps each checklist item to a planned test or an explicit blocker.
  3. Generated tests compile and pass with the narrowest relevant test command.
  4. Every explicit user requirement is backed by a concrete test and assertion. Fix missing mock seams, boundary cases, state transitions, and property combinations even when coverage already passes. In the final summary, cite at least one generated test name for every checklist item so completion is auditable; if an item has no test to cite, keep implementing or report it as blocked. For non-behavioral requirements such as scaffolding, scope limits, commands, or coverage artifacts, cite the relevant file, command, or report instead of forcing a test-name mapping. A passing suite with fewer tests is not automatically weaker: judge completeness by whether every independently requested behavior has direct, nonredundant evidence, not by raw test volume. For broad/comprehensive scope, also verify that every observable equivalence partition and invariant discovered in the bounded target APIs has one mutation-relevant case, even when the prompt did not name it. When the request names multiple modules, verify that each module's own non-trivial public behavior has direct test evidence in addition to any end-to-end composition test.
  5. Review the generated tests for behavior gaps and weak assertions. On a broad scope, invoke test-gap-analysis and assertion-quality when available and record the findings and fixes in <TESTAGENT_DIR>/status.md. On a focused scope, do the equivalent review inline — re-read each generated assertion against the source — without spawning extra passes.

The final response MUST include a compact Requirement | Evidence table. Behavioral rows cite exact generated test names. Non-behavioral rows cite the relevant project file, validation command, or coverage report. A generic list of tested areas is not a substitute for requirement-by-requirement evidence.

Quote the user's requirement verbatim in each row. When the request names a specific combination — "a case where a composite discount, regional tax, and weight-based shipping all apply", "the difference between summed and chained discounts", "constructor validation for every class" — the row must cite the one test that demonstrates exactly that. A test that merely exercises the same collaborators does not satisfy a requirement about their interaction, and per-class requirements need a citation per class.

Cite a clean run, not an attempt. The commands behind the evidence table must have finished successfully: quote the final passing test summary and, when thresholds were requested, the per-module coverage table from a run that exited 0. If the last coverage run exited non-zero, fix it and re-run before reporting; never infer threshold clearance from a failed or partial run.

Before reporting, inspect the final working-tree changes and confirm that research.md, plan.md, status.md, and any other intermediate state files are not among the changes intended for commit.

State Management

Broad-scope runs store intermediate state files in a non-stageable <TESTAGENT_DIR> backed by host scratch storage, Git metadata, or OS temp. A focused request does not create these files:

File Purpose
<TESTAGENT_DIR>/research.md Codebase analysis results
<TESTAGENT_DIR>/plan.md Phased implementation plan
<TESTAGENT_DIR>/status.md Final quality review and fixes

Agent Reference

Agent Purpose
code-testing-generator Coordinates pipeline
code-testing-researcher Analyzes codebase
code-testing-planner Creates test plan
code-testing-implementer Writes test files
code-testing-builder Compiles code
code-testing-tester Runs tests
code-testing-fixer Fixes errors
code-testing-linter Formats code

Requirements

  • Project must have a build/test system configured
  • Testing framework should be installed (or installable)
  • VS Code with GitHub Copilot extension

Classic non-SDK .NET projects are supported when their existing build/test toolchain is available. When it is not available on the current machine, the agent can still add and register version-compatible tests, but must report execution as blocked rather than substituting dotnet test.

Troubleshooting

Tests don't compile

The code-testing-fixer agent will attempt to resolve compilation errors. Check <TESTAGENT_DIR>/plan.md for the expected test structure. Call the code-testing-extensions skill and read the language-specific extension file for error code references (e.g., dotnet.md for .NET).

Tests fail

Most failures in generated tests are caused by wrong expected values in assertions, not production code bugs:

  1. Read the actual test output
  2. Read the production code to understand correct behavior
  3. Fix the assertion, not the production code
  4. Never mark tests [Ignore] or [Skip] just to make them pass

Wrong testing framework detected

Specify your preferred framework in the initial request: "Generate Jest tests for..."

Environment-dependent tests fail

Tests that depend on external services, network endpoints, specific ports, or precise timing will fail in CI environments. Focus on unit tests with mocked dependencies instead.

Build fails on full solution

During phase implementation, build only the specific test project for speed. After all phases, run a full non-incremental workspace build to catch cross-project errors.

Files (skills)
  • SKILL.md 18.3 KB
    ---
    name: code-testing-agent
    description: >-
      ALWAYS USE whenever asked to write, add, or generate unit tests for existing
      code, including one helper, function, class, or missing regression case as well
      as project-wide suites. Also use for "cover this untested method", scaffolding
      tests where none exist, sparse workspaces, classic packages.config MSTest, and
      extending healthy suites. Focused requests use a proportional direct workflow;
      broad requests use the full pipeline. DO NOT USE for only running/diagnosing
      tests, coverage/audits, a test blocked on a missing production seam
      (testability-obstacle), or correcting supplied MSTest assertions, attributes,
      lifecycle, or configuration without designing new cases (writing-mstest-tests).
    license: MIT
    ---
    
    # Code Testing Generation Skill
    
    An AI-powered skill that generates comprehensive, workable unit tests for any programming language using a coordinated multi-agent pipeline.
    
    ## Non-negotiable execution contract
    
    Classify scope **before editing**:
    
    - **Broad** (a project/package-wide suite, or multiple production
      files/modules): create `research.md` and `plan.md` in a resolved
      non-stageable `<TESTAGENT_DIR>` before implementation, then `status.md` there
      after the final test-quality review. If these files are absent, the broad
      workflow is incomplete.
    - **Focused** (the user explicitly limits work to one function/class/file or one
      missing method): do not create intermediate state files or fan out to multiple
      agents. A sparse project-wide request remains broad even when only one source
      module is present.
    
    For either scope, run the narrowest relevant test command to a clean exit and
    finish with a compact `Requirement | Evidence` table. Each requested behavior
    must cite an exact test name; validation rows cite the successful command.
    For focused work, "no intermediate state files" changes only the process, not the
    final evidence contract.
    
    Intermediate state files are internal working data, never deliverables. Keep
    `<TESTAGENT_DIR>` non-stageable, never place it or its files in
    version-controlled workspace content, and never modify `.gitignore` to hide
    them.
    
    Treat completeness as a requirement matrix, not a test-count target. Give every
    independently requested state, boundary, error path, or interaction its own
    concrete assertion. Combine cases only when one execution genuinely proves the
    whole requested combination; do not let a parameterized happy-path case stand in
    for an empty state, invalid discriminator, or before/at/after boundary.
    For broad requests that name several production modules or layers, give each
    named module direct tests for its non-trivial public behavior. Cross-module tests
    prove composition, but do not substitute for the requested module-level
    coverage. Judge breadth by the behavior matrix, never by matching or exceeding a
    raw test count.
    
    For a **broad or comprehensive** request, the explicit matrix is the floor, not
    the ceiling. After satisfying it, inspect each target API for observable
    equivalence partitions and invariants that the prompt did not name: identity,
    empty, singleton and representative interior inputs; exact boundaries plus an
    immediately adjacent value; invalid partitions; and ordering, monotonicity,
    rollover, capacity, truncation, or state invariants implied by the implementation.
    Add one mutation-relevant case per distinct partition not already proved, using
    parameterized or table-driven cases for siblings. Stop when remaining inputs
    exercise the same branch and invariant, not merely when the explicit checklist
    is complete; never add cases only to raise the count.
    
    ## When to Use This Skill
    
    Use this skill when you need to:
    
    - Generate unit tests for an entire project or specific files
    - Improve test coverage for existing codebases
    - Create test files that follow project conventions
    - Write tests that actually compile and pass
    - Add tests for new features or untested code
    - Generate or extend MSTest suites; load `writing-mstest-tests` as supporting
      guidance after this entry skill has established scope and project conventions
    
    ## When Not to Use
    
    - Running or executing existing tests (use the `run-tests` skill)
    - Migrating between test frameworks (use migration skills)
    - Answering an MSTest API/pattern or modernization question that does not ask to
      generate tests (use `writing-mstest-tests`)
    - Debugging failing test logic
    
    ## How It Works
    
    This skill coordinates multiple specialized agents in a **Research → Plan → Implement** pipeline:
    
    ### Pipeline Overview
    
    ```text
    ┌─────────────────────────────────────────────────────────────┐
    │                     TEST GENERATOR                          │
    │  Coordinates the full pipeline and manages state            │
    └─────────────────────┬───────────────────────────────────────┘
                          │
            ┌─────────────┼─────────────┐
            ▼             ▼             ▼
    ┌───────────┐  ┌───────────┐  ┌───────────────┐
    │ RESEARCHER│  │  PLANNER  │  │  IMPLEMENTER  │
    │           │  │           │  │               │
    │ Analyzes  │  │ Creates   │  │ Writes tests  │
    │ codebase  │→ │ phased    │→ │ per phase     │
    │           │  │ plan      │  │               │
    └───────────┘  └───────────┘  └───────┬───────┘
                                          │
                        ┌─────────┬───────┼───────────┐
                        ▼         ▼       ▼           ▼
                  ┌─────────┐ ┌───────┐ ┌───────┐ ┌───────┐
                  │ BUILDER │ │TESTER │ │ FIXER │ │LINTER │
                  │         │ │       │ │       │ │       │
                  │ Compiles│ │ Runs  │ │ Fixes │ │Formats│
                  │ code    │ │ tests │ │ errors│ │ code  │
                  └─────────┘ └───────┘ └───────┘ └───────┘
    ```
    
    ## Step-by-Step Instructions
    
    ### Step 1: Determine the user request
    
    Make sure you understand what user is asking and for what scope.
    When the user does not express strong requirements for test style, coverage goals, or conventions, source the guidelines from [unit-test-generation.prompt.md](unit-test-generation.prompt.md). This prompt provides best practices for discovering conventions, parameterization strategies, coverage goals (aim for 80%), and language-specific patterns.
    
    ### Step 2: Size the request before invoking anything
    
    Match the machinery to the scope. Running the full pipeline on a one-file
    request costs turns and tool calls without improving the tests.
    
    | Scope | What it looks like | How to run it |
    | --- | --- | --- |
    | **Focused** | One function, class, or file; "tests for X only"; extending an existing suite with the missing cases | Skip intermediate state files and the sub-agent fan-out. Keep the requirement checklist in your head (or in the final table), read only the target and one neighbouring test for conventions, write the tests, run the narrowest test command, review your own assertions inline. |
    | **Broad** | A project, package, or module set; "comprehensive suite"; a coverage threshold to clear across several files | Run the full Research → Plan → Implement pipeline in Step 3, with intermediate state files under `<TESTAGENT_DIR>` and the completion contract below. |
    
    When in doubt, start focused and escalate only if the request turns out to span
    several files. Escalating costs one extra pass; running the broad pipeline on a
    focused request costs several.
    
    Before ending a focused request, check all three conditions together:
    
    1. every named behavior has a concrete assertion, including each requested
       boundary or error path;
    2. the narrow test command exited successfully;
    3. the final `Requirement | Evidence` table maps those behaviors to exact test
       names and cites that successful command.
    
    Do not replace this table with a prose list of covered areas, even for a
    single-function request.
    
    ### Step 3: Invoke the Test Generator (broad scope)
    
    Start by calling the `code-testing-generator` agent with your test generation request:
    
    ```text
    Generate unit tests for [path or description of what to test], following the [unit-test-generation.prompt.md](unit-test-generation.prompt.md) guidelines. Treat the current workspace as authoritative even when it is sparse, gutted-looking, synthetic, or missing tracked files; never restore or reconstruct it, including with `git checkout`, `git restore`, `git reset`, or `git clean`.
    ```
    
    The Test Generator will manage the entire pipeline automatically.
    
    If `code-testing-generator` is unavailable, do not skip the workflow. Execute the
    same Research → Plan → Implement sequence inline, resolve `<TESTAGENT_DIR>` as
    described below, create the intermediate state files there, and apply the same
    completion contract.
    
    For broad scope, resolve one absolute `<TESTAGENT_DIR>` before creating
    intermediate state files:
    
    1. Prefer a host-provided session artifact or scratch directory.
    2. Otherwise, in a Git worktree run
       `git rev-parse --path-format=absolute --git-path testagent`; this returns a
       path in worktree-specific Git metadata that cannot be staged.
    3. Outside Git, create a unique directory under the operating system's
       temporary directory.
    
    Pass the absolute directory to every pipeline agent. The path may be inside the
    repository's `.git` metadata directory, but it must not be version-controlled
    workspace content, appear in `git status`, or be stageable.
    
    ### Step 4: Execute with bounded context
    
    For multi-file requests:
    
    1. Turn every explicit user requirement into a checklist before implementation. Include requested layers, collaborators to mock, boundary cases, integrations, coverage thresholds, and report artifacts. Copy multi-condition requirements verbatim — they must each map to one test that exercises the whole combination.
    2. Research only the requested module or project and write the checklist plus a compact target inventory to `<TESTAGENT_DIR>/research.md`.
    3. Reuse manifests, symbol references, and deterministic pairing tools instead of reading every source and test file.
    4. For multi-file scopes in C#, Python, TypeScript/JavaScript, Go, Java, Rust, Ruby, Kotlin, Swift, PowerShell, or C++, run `find-untested-sources` once and consume its pairing and suggested-path output; do not repeat that discovery manually.
    5. Plan each target file once, then implement phases sequentially. Map every checklist item to at least one concrete test or explain why it is blocked.
    6. Build and test the narrow target during fix cycles; run workspace-level validation once at the end.
    7. Before reporting success, re-open the generated tests and verify every checklist item against concrete test names and assertions. Coverage alone is not evidence that a requested mock seam, boundary, state transition, or property combination was tested.
    8. Read a language example from `code-testing-extensions` only when the repository has no representative tests and the base extension is insufficient.
    9. For .NET, classify SDK-style vs. classic non-SDK before choosing commands or creating files. In classic projects, preserve `packages.config`, existing framework/mock versions and custom base fixtures, add every new test file to the project's explicit `<Compile Include>` items, and use the repository's MSBuild/test-runner commands. Never modernize the project or dependency stack merely to generate tests.
    10. For MSTest, inspect the pinned package version before choosing exception
        assertions. MSTest 3.5.x uses `Assert.ThrowsException<T>`; do not substitute
        `[ExpectedException]`, `Assert.Throws<T>`, or `Assert.ThrowsExactly<T>`.
    
    ### Completion contract
    
    Every scope must satisfy points 3–5 below. Points 1 and 2 are the **broad-scope**
    artifacts: on a focused request the same reasoning happens inline and no
    intermediate state files are written.
    
    Do not report completion until all of these are true:
    
    1. *(broad scope)* `<TESTAGENT_DIR>/research.md` records the bounded target
       inventory, existing test conventions, and the acceptance checklist.
    2. *(broad scope)* `<TESTAGENT_DIR>/plan.md` maps each checklist item to a planned
       test or an explicit blocker.
    3. Generated tests compile and pass with the narrowest relevant test command.
    4. Every explicit user requirement is backed by a concrete test and assertion.
       Fix missing mock seams, boundary cases, state transitions, and property
       combinations even when coverage already passes. In the final summary, cite
       at least one generated test name for every checklist item so completion is
       auditable; if an item has no test to cite, keep implementing or report it as
       blocked. For non-behavioral requirements such as scaffolding, scope limits,
       commands, or coverage artifacts, cite the relevant file, command, or report
       instead of forcing a test-name mapping.
       A passing suite with fewer tests is not automatically weaker: judge
       completeness by whether every independently requested behavior has direct,
       nonredundant evidence, not by raw test volume.
       For broad/comprehensive scope, also verify that every observable equivalence
       partition and invariant discovered in the bounded target APIs has one
       mutation-relevant case, even when the prompt did not name it.
       When the request names multiple modules, verify that each module's own
       non-trivial public behavior has direct test evidence in addition to any
       end-to-end composition test.
    5. Review the generated tests for behavior gaps and weak assertions. On a broad
       scope, invoke `test-gap-analysis` and `assertion-quality` when available and
       record the findings and fixes in `<TESTAGENT_DIR>/status.md`. On a focused scope,
       do the equivalent review inline — re-read each generated assertion against
       the source — without spawning extra passes.
    
    The final response MUST include a compact `Requirement | Evidence` table.
    Behavioral rows cite exact generated test names. Non-behavioral rows cite the
    relevant project file, validation command, or coverage report. A generic list
    of tested areas is not a substitute for requirement-by-requirement evidence.
    
    **Quote the user's requirement verbatim in each row.** When the request names a
    specific combination — "a case where a composite discount, regional tax, and
    weight-based shipping all apply", "the difference between summed and chained
    discounts", "constructor validation for every class" — the row must cite the one
    test that demonstrates exactly that. A test that merely exercises the same
    collaborators does not satisfy a requirement about their interaction, and
    per-class requirements need a citation per class.
    
    **Cite a clean run, not an attempt.** The commands behind the evidence table must
    have finished successfully: quote the final passing test summary and, when
    thresholds were requested, the per-module coverage table from a run that exited
    0. If the last coverage run exited non-zero, fix it and re-run before reporting;
    never infer threshold clearance from a failed or partial run.
    
    Before reporting, inspect the final working-tree changes and confirm that
    `research.md`, `plan.md`, `status.md`, and any other intermediate state files are
    not among the changes intended for commit.
    
    ## State Management
    
    Broad-scope runs store intermediate state files in a non-stageable
    `<TESTAGENT_DIR>` backed by host scratch storage, Git metadata, or OS temp. A
    focused request does not create these files:
    
    | File                     | Purpose                      |
    | ------------------------ | ---------------------------- |
    | `<TESTAGENT_DIR>/research.md` | Codebase analysis results    |
    | `<TESTAGENT_DIR>/plan.md`     | Phased implementation plan   |
    | `<TESTAGENT_DIR>/status.md`   | Final quality review and fixes |
    
    ## Agent Reference
    
    | Agent                      | Purpose              |
    | -------------------------- | -------------------- |
    | `code-testing-generator`   | Coordinates pipeline |
    | `code-testing-researcher`  | Analyzes codebase    |
    | `code-testing-planner`     | Creates test plan    |
    | `code-testing-implementer` | Writes test files    |
    | `code-testing-builder`     | Compiles code        |
    | `code-testing-tester`      | Runs tests           |
    | `code-testing-fixer`       | Fixes errors         |
    | `code-testing-linter`      | Formats code         |
    
    ## Requirements
    
    - Project must have a build/test system configured
    - Testing framework should be installed (or installable)
    - VS Code with GitHub Copilot extension
    
    Classic non-SDK .NET projects are supported when their existing build/test
    toolchain is available. When it is not available on the current machine, the
    agent can still add and register version-compatible tests, but must report
    execution as blocked rather than substituting `dotnet test`.
    
    ## Troubleshooting
    
    ### Tests don't compile
    
    The `code-testing-fixer` agent will attempt to resolve compilation errors. Check
    `<TESTAGENT_DIR>/plan.md` for the expected test structure. Call the
    `code-testing-extensions` skill and read the language-specific extension file
    for error code references (e.g., `dotnet.md` for .NET).
    
    ### Tests fail
    
    Most failures in generated tests are caused by **wrong expected values in assertions**, not production code bugs:
    
    1. Read the actual test output
    2. Read the production code to understand correct behavior
    3. Fix the assertion, not the production code
    4. Never mark tests `[Ignore]` or `[Skip]` just to make them pass
    
    ### Wrong testing framework detected
    
    Specify your preferred framework in the initial request: "Generate Jest tests for..."
    
    ### Environment-dependent tests fail
    
    Tests that depend on external services, network endpoints, specific ports, or precise timing will fail in CI environments. Focus on unit tests with mocked dependencies instead.
    
    ### Build fails on full solution
    
    During phase implementation, build only the specific test project for speed. After all phases, run a full non-incremental workspace build to catch cross-project errors.
    
  • unit-test-generation.prompt.md 9.9 KB
    ---
    description: >-
      Best practices and guidelines for generating comprehensive,
      parameterized unit tests with 80% code coverage across any programming
      language
    ---
    
    # Unit Test Generation Prompt
    
    You are an expert code generation assistant specialized in writing concise, effective, and logical unit tests. You carefully analyze provided source code, identify important edge cases and potential bugs, and produce minimal yet comprehensive and high-quality unit tests that follow best practices and cover the whole code to be tested. Aim for 80% code coverage.
    
    ## Discover and Follow Conventions
    
    Before generating tests, analyze the codebase to understand existing conventions:
    
    - **Location**: Where test projects and test files are placed
    - **Naming**: Namespace, class, and method naming patterns
    - **Frameworks**: Testing, mocking, and assertion frameworks used
    - **Harnesses**: Preexisting setups, base classes, or testing utilities
    - **Guidelines**: Testing or coding guidelines in instruction files, README, or docs
    
    If you identify a strong pattern, follow it unless the user explicitly requests otherwise. If no pattern exists and there's no user guidance, use your best judgment.
    
    ## Test Generation Requirements
    
    Generate concise, parameterized, and effective unit tests using discovered conventions.
    
    - **Prefer mocking** over generating one-off testing types
    - **Prefer unit tests** over integration tests, unless integration tests are clearly needed and can run locally
    - **Traverse code thoroughly** to ensure high coverage (80%+) of the entire scope
    - Continue generating tests until you reach the coverage target or have covered all non-trivial public surface area
    
    ### Key Testing Goals
    
    | Goal                          | Description                                                                                          |
    | ----------------------------- | ---------------------------------------------------------------------------------------------------- |
    | **Minimal but Comprehensive** | Avoid redundant tests                                                                                |
    | **Logical Coverage**          | Focus on meaningful edge cases, domain-specific inputs, boundary values, and bug-revealing scenarios |
    | **Core Logic Focus**          | Test positive cases and actual execution logic; avoid low-value tests for language features          |
    | **Balanced Coverage**         | Don't let negative/edge cases outnumber tests of actual logic                                        |
    | **Best Practices**            | Use Arrange-Act-Assert pattern and proper naming (`Method_Condition_ExpectedResult`)                 |
    | **Buildable & Complete**      | Tests must compile, run, and contain no hallucinated or missed logic                                 |
    
    ## Quality over Quantity
    
    When the task specifies particular test scenarios or behaviors to cover:
    
    1. **Cover every stated requirement first** — each bullet point or scenario in the task description should map to at least one test
    2. **Test the actual implementation** — read the source code to understand return values, side effects, and error conditions before writing assertions
    3. **Fewer focused tests beat many shallow ones** — 5 tests that thoroughly exercise the function are better than 20 that only check surface behavior
    4. **Every test must pass** — run tests after writing them; fix immediately if they fail
    5. **Make completion auditable** — before finishing, cite at least one generated
       test name for every explicit behavioral requirement. For scaffolding, scope,
       commands, and coverage requirements, cite the relevant file or artifact.
       Passing coverage is not completion when a requested mock seam, boundary,
       transition, or property combination has no mapped test.
    
    ## Write Tests That Pin Down Behavior
    
    A test that passes coincidentally gives a false signal. Beyond covering code, every test must *pin down behavior* — it should fail under a plausible bug. These principles are language-agnostic (MSTest, xUnit, NUnit, pytest, Jest, Go `testing`, JUnit, RSpec, ...):
    
    - **Mutation thinking** — each assertion should fail under at least one plausible mutation (`>`→`>=`, `&&`→`||`, a dropped null/`None`/`nil` check, an off-by-one, returning the input unchanged). If it survives every mutation, replace weak checks (`IsNotNull`/`toBeDefined`) with a concrete expected value.
    - **No tautologies** — never assert that a value you just wrote reads back unchanged; assert on the *transformation* the code performs, not that storage works.
    - **Property intersections** — when code handles independent properties (quoted/unquoted, ASCII/escaped, present/absent), add at least one test combining several at once. Bugs live at intersections, not on single axes.
    - **Behavior radius** — assert on at least one *secondary* observable (related state, log output, neighboring field, retry counter, event), not only the return value.
    - **Fixture realism** — never set the parameter under test to a degenerate value (scroll with `scrollback=0`, eviction with `capacity=1`, retries with `maxRetries=0`, ordering with a single element).
    
    Quick self-review before finishing a test: would emptying the function body make it fail? If not, the assertions are too weak.
    
    ## Parameterization
    
    - Prefer parameterized tests (e.g., `[DataRow]`, `[Theory]`, `@pytest.mark.parametrize`) over multiple similar methods
    - Combine logically related test cases into a single parameterized method
    - Never generate multiple tests with identical logic that differ only by input values
    
    ## Analysis Before Generation
    
    Before writing tests:
    
    1. **Analyze** the code line by line to understand what each section does
    2. **Document** all parameters, their purposes, constraints, and valid/invalid ranges
    3. **Identify** potential edge cases and error conditions
    4. **Describe** expected behavior under different input conditions
    5. **Note** dependencies that need mocking
    6. **Consider** concurrency, resource management, or special conditions
    7. **Identify** domain-specific validation or business rules
    
    Apply this analysis to the **entire** code scope, not just a portion.
    
    ## Coverage Types
    
    | Type                  | Examples                                                            |
    | --------------------- | ------------------------------------------------------------------- |
    | **Happy Path**        | Valid inputs produce expected outputs                               |
    | **Edge Cases**        | Empty values, boundaries, special characters, zero/negative numbers |
    | **Error Cases**       | Invalid inputs, null handling, exceptions, timeouts                 |
    | **State Transitions** | Before/after operations, initialization, cleanup                    |
    
    ## Language-Specific Examples
    
    ### C# (MSTest)
    
    ```csharp
    [TestClass]
    public sealed class CalculatorTests
    {
        private readonly Calculator _sut = new();
    
        [TestMethod]
        [DataRow(2, 3, 5, DisplayName = "Positive numbers")]
        [DataRow(-1, 1, 0, DisplayName = "Negative and positive")]
        [DataRow(0, 0, 0, DisplayName = "Zeros")]
        public void Add_ValidInputs_ReturnsSum(int a, int b, int expected)
        {
            // Act
            var result = _sut.Add(a, b);
    
            // Assert
            Assert.AreEqual(expected, result);
        }
    
        [TestMethod]
        public void Divide_ByZero_ThrowsDivideByZeroException()
        {
            // Act & Assert
            Assert.ThrowsException<DivideByZeroException>(() => _sut.Divide(10, 0));
        }
    }
    ```
    
    ### TypeScript (Jest)
    
    ```typescript
    describe("Calculator", () => {
      let sut: Calculator;
    
      beforeEach(() => {
        sut = new Calculator();
      });
    
      it.each([
        [2, 3, 5],
        [-1, 1, 0],
        [0, 0, 0],
      ])("add(%i, %i) returns %i", (a, b, expected) => {
        expect(sut.add(a, b)).toBe(expected);
      });
    
      it("divide by zero throws error", () => {
        expect(() => sut.divide(10, 0)).toThrow("Division by zero");
      });
    });
    ```
    
    ### Python (pytest)
    
    ```python
    import pytest
    from calculator import Calculator
    
    class TestCalculator:
        @pytest.fixture
        def sut(self):
            return Calculator()
    
        @pytest.mark.parametrize("a,b,expected", [
            (2, 3, 5),
            (-1, 1, 0),
            (0, 0, 0),
        ])
        def test_add_valid_inputs_returns_sum(self, sut, a, b, expected):
            assert sut.add(a, b) == expected
    
        def test_divide_by_zero_raises_error(self, sut):
            with pytest.raises(ZeroDivisionError):
                sut.divide(10, 0)
    ```
    
    ## Output Requirements
    
    - Tests must be **complete and buildable** with no placeholder code
    - Follow the **exact conventions** discovered in the target codebase
    - Include **appropriate imports** and setup code
    - Add **brief comments** explaining non-obvious test purposes
    - Place tests in the **correct location** following project structure
    
    ## Build and Verification
    
    - **Scoped builds during development**: Build the specific test project during implementation for faster iteration
    - **Final full-workspace build**: After all test generation is complete, run a full non-incremental build from the workspace root to catch cross-project errors
    - **API signature verification**: Before calling any method in test code, verify the exact parameter types, count, and order by reading the source code
    - **Project reference validation**: Before writing test code, verify the test project references all source projects the tests will use. Call the `code-testing-extensions` skill and read the language-specific extension file for guidance (e.g., `dotnet.md` for .NET)
    
    ## Test Scope Guidelines
    
    - **Write unit tests, not integration/acceptance tests**: Focus on testing individual classes and methods with mocked dependencies
    - **No external dependencies**: Never write tests that call external URLs, bind to network ports, require service discovery, or depend on precise timing
    - **Mock everything external**: HTTP clients, database connections, file systems, network endpoints — all should be mocked in unit tests
    - **Fix assertions, not production code**: When tests fail, read the production code, understand its actual behavior, and update the test assertion
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related