Create Test
Purpose
Create or update tests to cover current changes according to project conventions.
Constraints
- Apply @rules/code-testing/general.mdc
- If the current project uses Laravel, also apply
@rules/laravel/laravel.mdc, @rules/laravel/architecture.mdc, @rules/laravel/filament.mdc, and @rules/laravel/livewire.mdc
- Do not modify production code unless strictly required — the only exception is the Pre-existing issue handling workflow below, which lands its production-code fixes in their own separate commits
Read, Map & Verify before writing tests (mandatory pre-flight)
Reading, mapping, and verifying come first; writing tests comes last. This pre-flight is blocking — do not add or modify a single line until all three steps pass, and never act on an assumption you have not confirmed by reading the code.
- Read — open and read the actual code under test and the code it depends on (callers, called methods, related existing tests, configuration). Confirm what the code does by reading it, not by guessing from names or the change description.
- Map — map the change's blast radius: every changed code path, its call sites, the data-flow branches a test must exercise, and the existing test conventions, helpers, and fixtures to reuse instead of reinventing.
- Verify — check your assumptions against the real code and its observed behavior (run the code path or an exploratory assertion where applicable). If what you read contradicts the change description, stop and surface the discrepancy instead of writing tests on a wrong premise.
Only after Read, Map, and Verify are complete may test-writing begin.
Execution
1. Analyze Context
- Locate existing tests
- Identify missing coverage for changed code
2. Create or Update Tests
- Prefer updating existing tests
- Create new tests only if necessary
- Follow project conventions and helpers
- Place new test files per
@rules/code-testing/general.mdc Test Organization — the test file path mirrors the namespace of the SUT (e.g. App\Service\Billing\InvoiceCalculator → tests/Service/Billing/InvoiceCalculatorTest.php), the file name is {ClassName}Test.php (or {ClassName}{Scenario}Test.php for an extracted scenario file of the same SUT), and cross-cutting tests sit under an intent-named directory (tests/Feature/<flow>, tests/Contract/<vendor>, tests/Integration/<area>).
- Name every
it() / test() block to match the scenario the body asserts — plain-language descriptions such as it('returns zero for an empty cart') or test('throws InvalidArgumentException when the discount is negative'). Never use placeholders (it('it works'), test('test1'), test('happy path')), method names (test('calculate'), it('handles getUser')), or descriptions that contradict the assertions. When changing what a test asserts, rename the description in the same change so the code-review test-organization gate passes downstream.
3. Ensure Coverage
- Cover all changed code paths
- Include:
- happy paths
- edge cases
- regression scenarios
4. Validate
- Run relevant tests after each change and confirm they pass
- Ensure deterministic behavior
- Remove flakiness
5. Verify Coverage
- Ensure 100% code coverage for all changed or added code paths
- If coverage tooling exists, verify coverage for the changed files only, using the project's available coverage tooling (per the Coverage gate in
@skills/code-review/SKILL.md) and verify the result. Do not gate on a project-wide coverage percentage — full-suite coverage is for release gates, not for verifying current changes. Delete any generated coverage report file once read so it is not accidentally committed.
6. Code Style and Quality Gates
- Discover available fixers and checkers (prefer Phing targets from
build.xml/phing.xml; fall back to Composer scripts in composer.json)
- Run available fixers on changed test files and fix any violations
- Run available checkers/analyzers on changed test files and resolve all reported errors by rewriting the flagged code, never by adding a suppression annotation (
@rules/php/core-standards.mdc PHP Practices)
7. Test Review
- Run a quick code review of the created/updated tests against
@rules/code-testing/general.mdc
- Fix any findings before finalizing
8. Pre-existing issue handling
While writing tests, you may uncover problems that are unrelated to the current change but were already present in the code you had to read or exercise. The following categories qualify:
- Bugs — incorrect logic, broken edge cases, or runtime errors revealed by exploratory test runs, but already present before this task.
- Project-rule violations — code that contradicts any rule listed in this skill's Constraints block or any other rule under
.claude/rules/.
- Security vulnerabilities — anything
@rules/security/backend.md, @rules/security/frontend.md, or @rules/security/mobile.md would flag.
Rules:
- Do not silently ignore a pre-existing issue you encountered in code you had to read or exercise to write the tests for the current change.
- Do not expand scope by actively scanning unrelated files for pre-existing issues. Limit attention to files already touched or exercised by the current change.
- Land each pre-existing fix (and its regression test) in its own separate commit, distinct from the test-coverage commit for the current change:
- Use a Conventional Commits subject per
@rules/git/general.mdc: fix(<scope>): pre-existing — <description> for bugs and security, refactor(<scope>): pre-existing — <description> for rule violations without behavior change.
- The
pre-existing — prefix is mandatory so reviewers can identify these commits at a glance.
- Test coverage workflow depends on the commit type:
fix(<scope>): pre-existing — … (bug, security) — add the regression test in the same commit as the fix; the test must fail before the fix lands and pass after.
refactor(<scope>): pre-existing — … (project-rule violation, behavior-preserving) — apply @rules/refactoring/general.mdc Test Coverage Contract: when the target lines are below 100% coverage, author a dedicated test(<scope>): cover <area> before pre-existing refactor commit before the refactor commit, and do not modify pre-existing tests inside the refactor commit (mechanical renames forced by the refactor itself stay exempt and must be flagged in the commit body).
- The "Do not modify production code unless strictly required" constraint above is overridden for these fixes — the production-code change is the fix itself, and it lives in its own commit.
- If a pre-existing issue is non-trivial (would significantly expand the change or requires architectural discussion), do not fix it. Surface it in the skill's output report as a deferred follow-up with the reason.
Output
- Created or updated test files
- Coverage status for current changes (must be 100%)
- Test review result
- List of pre-existing fix commits (if any), each with a one-line rationale, plus any pre-existing issue deferred as a follow-up with the reason
Principles
- Prefer updating existing tests over creating new ones
- Keep tests simple and deterministic
- Cover behavior, not implementation
- Focus on changed code only
- Follow project test conventions strictly
- Prefer minimal tests for maximum coverage
- Use data providers where they improve readability and reduce duplication
- Keep tests readable and maintainable
1---2name: create-test3description: Use when create or update tests to ensure full coverage for current changes4license: MIT5---67# Create Test89## Purpose10Create or update tests to cover current changes according to project conventions.1112---1314## Constraints15- Apply @rules/code-testing/general.mdc16- If the current project uses Laravel, also apply `@rules/laravel/laravel.mdc`, `@rules/laravel/architecture.mdc`, `@rules/laravel/filament.mdc`, and `@rules/laravel/livewire.mdc`17- Do not modify production code unless strictly required — the only exception is the **Pre-existing issue handling** workflow below, which lands its production-code fixes in their own separate commits1819---2021## Read, Map & Verify before writing tests (mandatory pre-flight)2223Reading, mapping, and verifying come first; writing tests comes last. This pre-flight is **blocking** — do not add or modify a single line until all three steps pass, and never act on an assumption you have not confirmed by reading the code.24251. **Read** — open and read the actual code under test and the code it depends on (callers, called methods, related existing tests, configuration). Confirm what the code does by reading it, not by guessing from names or the change description.262. **Map** — map the change's blast radius: every changed code path, its call sites, the data-flow branches a test must exercise, and the existing test conventions, helpers, and fixtures to reuse instead of reinventing.273. **Verify** — check your assumptions against the real code and its observed behavior (run the code path or an exploratory assertion where applicable). If what you read contradicts the change description, stop and surface the discrepancy instead of writing tests on a wrong premise.2829Only after Read, Map, and Verify are complete may test-writing begin.3031---3233## Execution3435### 1. Analyze Context36- Locate existing tests37- Identify missing coverage for changed code3839### 2. Create or Update Tests40- Prefer updating existing tests41- Create new tests only if necessary42- Follow project conventions and helpers43- **Place new test files per `@rules/code-testing/general.mdc` *Test Organization*** — the test file path mirrors the namespace of the SUT (e.g. `App\Service\Billing\InvoiceCalculator` → `tests/Service/Billing/InvoiceCalculatorTest.php`), the file name is `{ClassName}Test.php` (or `{ClassName}{Scenario}Test.php` for an extracted scenario file of the same SUT), and cross-cutting tests sit under an intent-named directory (`tests/Feature/<flow>`, `tests/Contract/<vendor>`, `tests/Integration/<area>`).44- **Name every `it()` / `test()` block to match the scenario the body asserts** — plain-language descriptions such as `it('returns zero for an empty cart')` or `test('throws InvalidArgumentException when the discount is negative')`. Never use placeholders (`it('it works')`, `test('test1')`, `test('happy path')`), method names (`test('calculate')`, `it('handles getUser')`), or descriptions that contradict the assertions. When changing what a test asserts, rename the description in the same change so the code-review test-organization gate passes downstream.4546### 3. Ensure Coverage47- Cover all changed code paths48- Include:49 - happy paths50 - edge cases51 - regression scenarios5253### 4. Validate54- Run relevant tests after each change and confirm they pass55- Ensure deterministic behavior56- Remove flakiness5758### 5. Verify Coverage59- Ensure 100% code coverage for all changed or added code paths60- If coverage tooling exists, verify coverage **for the changed files only**, using the project's available coverage tooling (per the Coverage gate in `@skills/code-review/SKILL.md`) and verify the result. Do not gate on a project-wide coverage percentage — full-suite coverage is for release gates, not for verifying current changes. Delete any generated coverage report file once read so it is not accidentally committed.6162### 6. Code Style and Quality Gates63- Discover available fixers and checkers (prefer Phing targets from `build.xml`/`phing.xml`; fall back to Composer scripts in `composer.json`)64- Run available fixers on changed test files and fix any violations65- Run available checkers/analyzers on changed test files and resolve all reported errors **by rewriting the flagged code, never by adding a suppression annotation** (`@rules/php/core-standards.mdc` PHP Practices)6667### 7. Test Review68- Run a quick code review of the created/updated tests against `@rules/code-testing/general.mdc`69- Fix any findings before finalizing7071### 8. Pre-existing issue handling7273While writing tests, you may uncover problems that are **unrelated to the current change** but were already present in the code you had to read or exercise. The following categories qualify:7475- **Bugs** — incorrect logic, broken edge cases, or runtime errors revealed by exploratory test runs, but already present before this task.76- **Project-rule violations** — code that contradicts any rule listed in this skill's *Constraints* block or any other rule under `.claude/rules/`.77- **Security vulnerabilities** — anything `@rules/security/backend.md`, `@rules/security/frontend.md`, or `@rules/security/mobile.md` would flag.7879Rules:80811. **Do not silently ignore** a pre-existing issue you encountered in code you had to read or exercise to write the tests for the current change.822. **Do not expand scope** by actively scanning unrelated files for pre-existing issues. Limit attention to files already touched or exercised by the current change.833. Land each pre-existing fix (and its regression test) in its **own separate commit**, distinct from the test-coverage commit for the current change:84 - Use a Conventional Commits subject per `@rules/git/general.mdc`: `fix(<scope>): pre-existing — <description>` for bugs and security, `refactor(<scope>): pre-existing — <description>` for rule violations without behavior change.85 - The `pre-existing — ` prefix is mandatory so reviewers can identify these commits at a glance.86 - **Test coverage workflow depends on the commit type:**87 - `fix(<scope>): pre-existing — …` (bug, security) — add the regression test in the **same commit** as the fix; the test must fail before the fix lands and pass after.88 - `refactor(<scope>): pre-existing — …` (project-rule violation, behavior-preserving) — apply `@rules/refactoring/general.mdc` *Test Coverage Contract*: when the target lines are below 100% coverage, author a dedicated `test(<scope>): cover <area> before pre-existing refactor` commit **before** the refactor commit, and do **not** modify pre-existing tests inside the refactor commit (mechanical renames forced by the refactor itself stay exempt and must be flagged in the commit body).894. The "Do not modify production code unless strictly required" constraint above is **overridden** for these fixes — the production-code change is the fix itself, and it lives in its own commit.905. If a pre-existing issue is **non-trivial** (would significantly expand the change or requires architectural discussion), do **not** fix it. Surface it in the skill's output report as a deferred follow-up with the reason.9192---9394## Output9596- Created or updated test files97- Coverage status for current changes (must be 100%)98- Test review result99- List of pre-existing fix commits (if any), each with a one-line rationale, plus any pre-existing issue deferred as a follow-up with the reason100101---102103## Principles104105- Prefer updating existing tests over creating new ones106- Keep tests simple and deterministic107- Cover behavior, not implementation108- Focus on changed code only109- Follow project test conventions strictly110- Prefer minimal tests for maximum coverage111- Use data providers where they improve readability and reduce duplication112- Keep tests readable and maintainable