Repository context. Gather first
Collect these with individual Bash calls, one command per call, never combined into a single
invocation:
- Current branch,
git branch --show-current
- Working tree status (empty = clean),
git status --porcelain | head -20
The pipe is the bound and belongs in the command. A read-time cap ("read only the first 20 entries")
bounds nothing: the Bash tool returns the command's complete output into context before there is
anything to decide about.
Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as
separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute
block as one shell invocation, and a worktree-isolated session refuses a compound command that
contains git. The dated record for that composition claim is the worktree skill's
reference/gather-block.md,
"The pre-compute block runs as one shell invocation".
Purpose
Authoring discipline for tests: what to test, how to name it, which test type fits, and where the test lives. /implementation:implement calls this skill during its TDD cadence; /toolchain:check owns test INVOCATION (the actual commands, SSOT). Test STRUCTURE configuration (frameworks, project locations, naming, fixture conventions) belongs to the consuming project. Read its testing conventions (its CLAUDE.md / rules / test-structure docs) before writing tests, and infer from existing test projects when nothing is documented.
Arguments
$ARGUMENTS, optional task description. organize (or a placement-shaped question) routes to the placement guidance; anything else is authoring.
Step 0: Route
| Signal |
Context file |
| Writing new tests, TDD, "test this code" |
context/write.md |
| "Where should this test go", new test project decision, fixture patterns |
context/organize.md |
Read the relevant context file before proceeding. Both draw on the consuming project's testing conventions for per-ecosystem naming, locations, and fixtures.
Step 1: Prerequisites
- Branch correct? Don't write code on the default branch in a PR-based workflow
- Test frameworks available? Identify the frameworks the project already uses (existing test projects, package manifests)
- Tests exist for the area? Check for test projects covering the changed area. If none exist and code has testable behavior, flag it
Cross-cutting principles
- Test behavior, not implementation. Assert on what the user sees or what the API returns, not internal state (Kent C. Dodds: "The more your tests resemble the way your software is used, the more confidence they can give you")
- Four Pillars (Vladimir Khorikov): protection against regressions, resistance to refactoring, fast feedback, maintainability. Every test scores well on all four
- Naming. Use the project's documented naming pattern; when undocumented, mirror the consuming ecosystem's own idiom (never impose one language's convention on another). The forms below are illustrative (.NET/xUnit). Adapt casing/separators to the target ecosystem: unit
{Method}_Should{Behavior}_When{Condition}, integration {Subject}_{Behavior}, architecture {Subject}_Should{Constraint}
- When uncertain about a testing decision (mock or not, output vs state test), load
/tdd:principles (when the tdd plugin is installed) for authoritative Beck/Khorikov guidance
Handoff
- Run the new tests by invoking
/toolchain:check via the Skill tool (or the project's own test command when the toolchain plugin is absent), then continue implementation. Invoke /implementation:implement via the Skill tool when that plugin is installed
- For HIGH/CRITICAL test suites (new domain logic, security-critical behavior, regression-prone paths, mocks of non-trivial dependencies, non-deterministic dependencies like clock/random/network) call the
advisor tool (when available in the session). Rubber-duck checkpoint before commit. Lightweight cross-model critique catches false-green or brittle tests before slow CI runs, the author writing tests for their own code is the producer verifying its own work, and this cross-model pass is that independence seam. Skip for trivial test additions
- After an
organize decision: proceed to authoring for the new test project
- Coverage gaps still open → invoke
/testing:plan via the Skill tool; failures while running → invoke /testing:diagnose via the Skill tool
What this skill does NOT do
- Does not run test commands.
/toolchain:check is SSOT for CLI invocation
- Does not diagnose failures.
/testing:diagnose
- Does not replace the project's testing conventions, the consuming project's rules are the source of truth for frameworks, naming, organization; this skill defers to them
Gotchas
- Framework traps.
.NET: under the Microsoft Testing Platform runner, --nologo is not a platform option and an unrecognized option exits 5, an invalid-argument code rather than a zero-test result; the banner switch there is --no-banner and the native xUnit v3 spelling is -noLogo, while -v q is an accepted dotnet test verbosity value. In that runner dotnet test takes --project, --solution, or --test-modules and no positional path, with --project defaulting to the current directory. The runner is selected by global.json and the classic runner is still the default, so confirm which one the project uses. Nesting a test project inside another project's directory is a real trap, but the cause is the base SDK's recursive **/*.cs compile glob rather than anything specific to the Web SDK, so it applies to any SDK-style project. Check the consuming project's own gotcha notes before writing tests. Verified 2026-09-06 against the vendor's testing-platform CLI options, dotnet test reference, and project-SDK overview pages; recheck when the platform option list gains --nologo, the runner-selection default changes, or the default compile glob changes
- Shared-state workarounds (collection fixtures, process-global singletons) are repo-specific. Consult the consuming project's testing conventions before writing or moving tests in affected areas
1---2name: write-23description: Write and place tests across all ecosystems. TDD cadence (Red→Green→Refactor in vertical slices), test naming, test-type selection, project placement, and fixture patterns. Use when: the user wants tests written or coverage added for code ('test this', 'write a unit test'), asks where a test should go, or code was just written without tests; for diagnosing failures use /testing:diagnose, for coverage-gap analysis /testing:plan, for running tests /toolchain:check.4---56## Repository context. Gather first78Collect these with **individual** Bash calls, one command per call, never combined into a single9invocation:1011- Current branch, `git branch --show-current`12- Working tree status (empty = clean), `git status --porcelain | head -20`1314The pipe is the bound and belongs in the command. A read-time cap ("read only the first 20 entries")15bounds nothing: the Bash tool returns the command's complete output into context before there is16anything to decide about.1718Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as19separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute20block as one shell invocation, and a worktree-isolated session refuses a compound command that21contains git. The dated record for that composition claim is the worktree skill's22[reference/gather-block.md](https://raw.githubusercontent.com/melodic-software/claude-code-plugins/main/plugins/source-control/skills/worktree/reference/gather-block.md),23"The pre-compute block runs as one shell invocation".2425## Purpose2627Authoring discipline for tests: what to test, how to name it, which test type fits, and where the test lives. `/implementation:implement` calls this skill during its TDD cadence; `/toolchain:check` owns test INVOCATION (the actual commands, SSOT). Test STRUCTURE configuration (frameworks, project locations, naming, fixture conventions) belongs to the consuming project. Read its testing conventions (its `CLAUDE.md` / rules / test-structure docs) before writing tests, and infer from existing test projects when nothing is documented.2829## Arguments3031`$ARGUMENTS`, optional task description. `organize` (or a placement-shaped question) routes to the placement guidance; anything else is authoring.3233## Step 0: Route3435| Signal | Context file |36|--------|-------------|37| Writing new tests, TDD, "test this code" | [context/write.md](context/write.md) |38| "Where should this test go", new test project decision, fixture patterns | [context/organize.md](context/organize.md) |3940Read the relevant context file before proceeding. Both draw on the consuming project's testing conventions for per-ecosystem naming, locations, and fixtures.4142## Step 1: Prerequisites4344- **Branch correct?** Don't write code on the default branch in a PR-based workflow45- **Test frameworks available?** Identify the frameworks the project already uses (existing test projects, package manifests)46- **Tests exist for the area?** Check for test projects covering the changed area. If none exist and code has testable behavior, flag it4748## Cross-cutting principles4950- **Test behavior, not implementation**. Assert on what the user sees or what the API returns, not internal state (Kent C. Dodds: "The more your tests resemble the way your software is used, the more confidence they can give you")51- **Four Pillars** (Vladimir Khorikov): protection against regressions, resistance to refactoring, fast feedback, maintainability. Every test scores well on all four52- **Naming**. Use the project's documented naming pattern; when undocumented, mirror the consuming ecosystem's own idiom (never impose one language's convention on another). The forms below are illustrative (.NET/xUnit). Adapt casing/separators to the target ecosystem: unit `{Method}_Should{Behavior}_When{Condition}`, integration `{Subject}_{Behavior}`, architecture `{Subject}_Should{Constraint}`53- When uncertain about a testing decision (mock or not, output vs state test), load `/tdd:principles` (when the `tdd` plugin is installed) for authoritative Beck/Khorikov guidance5455## Handoff5657- Run the new tests by invoking `/toolchain:check` via the Skill tool (or the project's own test command when the `toolchain` plugin is absent), then continue implementation. Invoke `/implementation:implement` via the Skill tool when that plugin is installed58- **For HIGH/CRITICAL test suites** (new domain logic, security-critical behavior, regression-prone paths, mocks of non-trivial dependencies, non-deterministic dependencies like clock/random/network) call the `advisor` tool (when available in the session). Rubber-duck checkpoint before commit. Lightweight cross-model critique catches false-green or brittle tests before slow CI runs, the author writing tests for their own code is the producer verifying its own work, and this cross-model pass is that independence seam. Skip for trivial test additions59- After an `organize` decision: proceed to authoring for the new test project60- Coverage gaps still open → invoke `/testing:plan` via the Skill tool; failures while running → invoke `/testing:diagnose` via the Skill tool6162## What this skill does NOT do6364- **Does not run test commands**. `/toolchain:check` is SSOT for CLI invocation65- **Does not diagnose failures**. `/testing:diagnose`66- **Does not replace the project's testing conventions**, the consuming project's rules are the source of truth for frameworks, naming, organization; this skill defers to them6768## Gotchas6970- Framework traps. `.NET`: under the Microsoft Testing Platform runner, `--nologo` is not a platform option and an unrecognized option exits 5, an invalid-argument code rather than a zero-test result; the banner switch there is `--no-banner` and the native xUnit v3 spelling is `-noLogo`, while `-v q` is an accepted `dotnet test` verbosity value. In that runner `dotnet test` takes `--project`, `--solution`, or `--test-modules` and no positional path, with `--project` defaulting to the current directory. The runner is selected by `global.json` and the classic runner is still the default, so confirm which one the project uses. Nesting a test project inside another project's directory is a real trap, but the cause is the base SDK's recursive `**/*.cs` compile glob rather than anything specific to the Web SDK, so it applies to any SDK-style project. Check the consuming project's own gotcha notes before writing tests. Verified 2026-09-06 against the vendor's testing-platform CLI options, `dotnet test` reference, and project-SDK overview pages; recheck when the platform option list gains `--nologo`, the runner-selection default changes, or the default compile glob changes71- Shared-state workarounds (collection fixtures, process-global singletons) are repo-specific. Consult the consuming project's testing conventions before writing or moving tests in affected areas