test-02 reproduction
Public source retained with the related article. Generated results, dependency directories, runtime storage, secrets, and oversized binary artifacts are intentionally excluded.
README
# TEST-02 boundary experiment
This fixture supports the planned article *Choose the Test Boundary from the
Defect*. It asks a narrow question: which test boundary can observe a given
class of defect, and which adjacent test remains green because it cannot?
The fixture is intentionally small. It is not an example application or a
recommendation to build four test suites for every feature.
## Run it
Docker with Compose v2 is the only host dependency.
```sh
./run.sh all
```
Each boundary can also be reproduced independently:
```sh
./run.sh unit
./run.sh integration
./run.sh contract
./run.sh e2e
```
The runner builds digest-pinned images, starts disposable services, runs the
clean case, seeds one defect, and verifies the expected failure. It returns a
non-zero status if a clean test fails or a seeded defect escapes. Containers
and the database volume are removed on exit.
Results are retained under `results/`. Every check records the exact command,
exit code, wall-clock duration, and unedited program output except for removal
of trailing whitespace.
## Boundary inventory
| Boundary | Real dependency crossed | Seeded defect | Negative control |
| --- | --- | --- | --- |
| Unit | PHP process and domain object | zero quantity is accepted | none; this is the narrowest case |
| Integration | PostgreSQL schema and constraint | uniqueness constraint is absent | in-memory repository still rejects duplicates |
| Contract | Compose network and HTTP provider | `available` becomes `stock` | consumer test with a stub still passes |
| End to end | generated JavaScript, browser, HTTP, Laravel, PostgreSQL | JavaScript submits an empty string | internal Laravel HTTP test still passes |
The negative controls matter. Without them, a failing wider test only proves
that some check noticed a defect. The controls demonstrate why a plausible
narrower test cannot observe that particular failure.
The concrete execution boundaries are:
| Boundary | Processes | Network hops | Storage engine | Generated asset |
| --- | --- | --- | --- | --- |
| Unit | one transient PHP test process | none used | none | none |
| Integration | PHP test process and PostgreSQL server | PostgreSQL TCP over the Compose network | PostgreSQL 17.6 | none |
| Contract | PHP consumer test and PHP provider server | HTTP over the Compose network | none | none |
| End to end | Chromium, PHP web server, and PostgreSQL server | browser HTTP plus PostgreSQL TCP over the Compose network | PostgreSQL 17.6 | `public/app.js`, built in the PHP image |
Compose creates an isolated network for the project even when the unit test
does not use it. “None used” means the test process opens no application
network connection; it does not mean Docker creates no network namespace.
## Defect switches
The runner controls four explicit switches:
- `POLICY_DEFECT=1` bypasses the zero-quantity policy.
- `DB_DEFECT=1` creates the reservations table without its unique constraint.
- `PROVIDER_DEFECT=1` changes the provider response field.
- `BROWSER_DEFECT=1` makes the generated client submit an empty quantity.
These switches exist only to make the counterfactual repeatable. They are not
runtime feature flags and do not represent a production deployment technique.
## Toolchain
The Dockerfiles pin PHP, Composer, Playwright, and PostgreSQL images by version
and digest. `composer.lock` and `package-lock.json` pin application and browser
dependencies. The runner records framework and test-runner versions plus
Composer and npm audit output with every run.
Durations describe this fixture on the machine that produced the retained
results. They are evidence about reproducibility and relative setup cost, not
general performance benchmarks.
Retained files
- .dockerignore
- app/Domain/AllocationPolicy.php
- app/Domain/InMemoryReservationRepository.php
- app/Inventory/HttpInventoryAvailability.php
- app/Inventory/InventoryAvailability.php
- app/Inventory/ReserveAgainstInventory.php
- artisan
- assets/app.js
- bootstrap/app.php
- browser/playwright.config.mjs
- browser/reservation.spec.mjs
- build.mjs
- compose.yaml
- composer.json
- composer.lock
- config/database.php
- config/logging.php
- database/migrations/2026_07_21_000000_create_reservations_table.php
- Dockerfile
- Dockerfile.browser
- package-lock.json
- package.json
- phpunit.xml
- provider/router.php
- public/index.php
- public/server.php
- README.md
- routes/web.php
- run.sh
- tests/Contract/InventoryProviderContractTest.php
- tests/Http/InternalReservationRequestTest.php
- tests/Integration/DatabaseUniquenessTest.php
- tests/TestCase.php
- tests/Unit/AllocationPolicyTest.php
- tests/Unit/ConsumerWithStubTest.php
- tests/Unit/InMemoryReservationRepositoryTest.php