Use when reviewing UI for accessibility — WCAG 2.2 AA, keyboard nav, focus, ARIA, contrast, screen-reader semantics — even on 'is this a11y-OK?' or 'mach das barrierefrei'.
The English summary is being prepared. Showing the original description.
Use when writing, generating, or improving Pest tests for Laravel — clear intent, good coverage, maintainable structure, and alignment with project testing conventions.
The English summary is being prepared. Showing the original description.
See how to installReview the instructions the agent will receive before you install.
Use this skill for all Laravel testing tasks, especially when working with:
This skill extends php-coder, laravel, and eloquent.
For prevention layers that fire before writing a test — TDD
discipline, mock-isolation gates, and the 12 process rationalizations
("I'll add the test after", "patch first, test later") — see
test-driven-development,
testing-anti-patterns, and
process-anti-patterns.md.
php-coder, laravel, and eloquent where relevant.test-case-discovery funnel; floor per behavior: 1 happy + 1 boundary + 1 error (+1 abuse on security paths).For bug fixes and new features, prefer test-driven development:
Tests written after implementation pass immediately. Passing immediately proves nothing:
For every bug fix: write a failing test that reproduces the bug FIRST, then fix it. The test proves the fix works AND prevents regression.
| Excuse | Reality |
|---|---|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests passing immediately prove nothing. |
| "Manual test is faster" | Manual doesn't prevent regression. You'll re-test every change. |
| "Test is hard to write" | Hard to test = hard to use. Simplify the design. |
| "Need to explore first" | Fine — throw away exploration code, start fresh with TDD. |
| "Existing code has no tests" | You're improving it. Add tests for what you touch. |
RefreshDatabase or the project's standard database reset strategy where appropriate.it() / test() according to existing project conventions.readonly or final on Pest test classes.final if they need to be mocked via Mockery::mock().namespace declaration) treat all PHP built-in classes as global.
Do NOT add use statements for global classes like DateTimeImmutable, Exception,
stdClass, etc. — PHP will warn: "The use statement with non-compound name has no effect".use statements for namespaced classes (e.g., use App\Models\...) are needed.$this->travel(5)->seconds() (Laravel's time travel) to create
a clear gap between "before" and "after" timestamps. Never rely on now() being different
between two lines of code — on fast hardware, they can be identical.null just because the seeder
doesn't set them — previous tests in parallel may have modified the same record.200 — verify meaningful behavior.assertDatabaseHasassertDatabaseMissingcoduo/php-matcherThis project uses coduo/php-matcher for flexible snapshot assertions.
Pattern files live in snapshots/ directories next to the test files.
Use pattern variables instead of hardcoded values in snapshot files. This makes snapshots resilient to data changes while still enforcing type correctness.
| Pattern | Matches | Example |
|---|---|---|
@boolean@ | true or false | 'is_active' => '@boolean@' |
@integer@ | Any integer | 'id' => '@integer@' |
@string@ | Any string | 'name' => '@string@' |
@null@ | null | 'deleted_at' => '@null@' |
@datetime@ | ISO datetime string | 'created_at' => '@datetime@' |
@uuid@ | UUID string | 'uuid' => '@uuid@' |
@array@ | Any array | 'items' => '@array@' |
@double@ | Any float | 'amount' => '@double@' |
@wildcard@ | Anything | 'data' => '@wildcard@' |
Combine with || for nullable fields: 'deleted_at' => '@null@||@datetime@'
$replacements.false) when other booleans in the same file use @boolean@ — be consistent.$variable ?? '@pattern@' syntax to allow test-specific overrides via replacements parameter.PhpMatcherHelper::ruleBackedEnum(EnumClass::class, 'string') for enum fields.// snapshots/user-resource.php
return [
'id' => $id ?? '@integer@',
'name' => $name ?? '@string@',
'email' => $email ?? '@string@',
'is_active' => $is_active ?? '@boolean@',
'created_at' => $created_at ?? '@datetime@',
'deleted_at' => $deleted_at ?? '@null@||@datetime@',
];
expect($response->json())
->toMatchPhpPatternFile(
patternFile: __DIR__ . '/snapshots/user-resource.php',
replacements: ['id' => $user->getId()],
);
Queue::fake()Bus::fake()Event::fake()Mail::fake()Notification::fake()Storage::fake()When reviewing or auditing existing tests, check for these anti-patterns:
| Smell | Description | Fix |
|---|---|---|
| Overmocking | Too many mocks disconnect the test from reality | Replace mocks with real implementations or fakes |
| Fragile tests | Tests break with unrelated changes (e.g., asserting exact JSON structure) | Assert only meaningful fields |
| Flaky tests | Non-deterministic results (time, ordering, parallel state) | Use time travel, explicit ordering, isolated data |
| Giant tests | One test covers 5+ behaviors | Split into focused tests |
| Missing assertions | Test runs code but doesn't verify outcomes | Add meaningful assertions |
| Test duplication | Same scenario tested in multiple places | Consolidate or use datasets |
| Assertion roulette | Many assertions without clear failure messages | Use named assertions or split tests |
| Eager test | Tests too many things, making failures hard to diagnose | One behavior per test |
Queue::fake(), Http::fake()) over manual mocks.When generating Pest tests:
When triaging a verbose run, narrow the output with --filter (Pest)
plus targeted grep/rg instead of re-running the whole suite or
echoing all logs:
# Only run failing tests in one file
vendor/bin/pest tests/Feature/InvoiceTest.php --filter='creates invoice'
# Scan the test log for failures only
rg --color=never '^FAIL|Tests:' storage/logs/pest.log
# Inspect JSON output from data-driven tests
vendor/bin/pest --log-junit=pest.xml && rg '<failure' pest.xml
readonly or final on Pest test helper classes — it breaks mocking.use statements for global classes (Exception, DateTimeImmutable) in Pest files — they're auto-imported.$this->travel(5)->seconds() for time-dependent tests — never rely on now() differing between lines.When generating new tests, focus on:
What NOT to test:
Quality over quantity — 5 meaningful tests beat 20 trivial ones.
No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
Use when reviewing UI for accessibility — WCAG 2.2 AA, keyboard nav, focus, ARIA, contrast, screen-reader semantics — even on 'is this a11y-OK?' or 'mach das barrierefrei'.
The English summary is being prepared. Showing the original description.
Use when defining or auditing the activation event — aha-moment selection, retention correlation, falsifiable definition. Triggers on 'what is our aha moment', 'redefine activation'.
The English summary is being prepared. Showing the original description.
Use when capturing an architectural decision — file naming, next ADR number, Status / Context / Decision / Consequences, index regen; fires even without saying 'ADR'.
The English summary is being prepared. Showing the original description.
Adversarial critique — devil's advocate, stress-test, honest teardown ('poke holes', 'be brutal', 'was hältst du davon'); explicit request only. Routine code or design review → code-review.
The English summary is being prepared. Showing the original description.
Use when reading, creating, or updating agent documentation, module docs, roadmaps, or AGENTS.md. Understands the full .augment/, agents/, and copilot-instructions structure.
The English summary is being prepared. Showing the original description.
Use for an adversarial red-team / blue-team / auditor review of an AI agent's CONFIG + behaviour (rules, skills, MCP, hooks, permissions) — attack-chain → defensive-gap list, not a code audit.
The English summary is being prepared. Showing the original description.