tdd-with-phpunit · diff
git:20261005.042befb to git:20261005.625d3c1
17 added, 12 removed. Audit A to A.
---
name: tdd-with-phpunit
description: Apply RED-GREEN-REFACTOR with PHPUnit 10/11 for Symfony; KernelTestCase/WebTestCase, attributes (#[Test]/#[DataProvider]), Foundry
capabilities: [read, search, edit, shell]
tags: [testing, tdd]
# projected by `bun run build` — do not edit by hand
allowed-tools:
- Read
- Glob
- Grep
- Write
- Edit
- Bash
---
# Tdd With Phpunit (Symfony)
## Use when
- - Building regression-safe behavior with TDD/functional/e2e tests.
- - Converting bug reports into executable failing tests.
+ - Driving a feature with RED-GREEN-REFACTOR using PHPUnit 10/11 class-based tests.
+ - Choosing between `TestCase`, `KernelTestCase` and `WebTestCase` for a new behavior.
+ - Testing a console command, or an invalid form that must answer 422.
+ - Swapping an external service for a double through the test container.
## Default workflow
- 1. Write failing test for target behavior and one boundary case.
- 2. Implement minimal code to pass.
- 3. Refactor while preserving green suite.
- 4. Broaden coverage for invalid/unauthorized/not-found paths.
+ 1. RED: pick the base class, write the test with `#[Test]`, `#[DataProvider]` and `#[CoversClass]`, run it and check it fails for the right reason.
+ 2. GREEN: write the minimum code that passes.
+ 3. REFACTOR with the suite green, re-running it after each change.
+ 4. Replace an external boundary with `static::getContainer()->set(Service::class, $mock)`.
+ 5. Test commands with `CommandTester`, or with `runCommand()` and `assertCommandIsSuccessful()` on Symfony 8.1+.
+ 6. Assert invalid form submissions with `assertResponseIsUnprocessable()`.
## Guardrails
- - Prefer deterministic fixtures/builders.
- - Assert observable behavior, not internal implementation.
- - Keep tests isolated and stable in CI.
+ - Use PHPUnit 10+ attributes, not `@test` or `@dataProvider` annotations.
+ - Fetch services with `static::getContainer()`, not the legacy `self::$container`.
+ - Mock only true external boundaries (HTTP clients, third-party SDKs); keep real services and a real database elsewhere.
+ - `runCommand()` and closures in `getContainer()->set()` need Symfony 8.1+.
## Progressive disclosure
- Use this file for execution posture and risk controls.
- Open references when deep implementation details are needed.
## Output contract
- - RED/GREEN/REFACTOR trace.
- - Test files changed and executed commands.
- - Coverage and confidence notes.
+ - The failing PHPUnit output (RED), then the passing run.
+ - Test files changed, with the base class and attributes used.
+ - Commands executed.
## References
- `reference.md`