The PHP package mirrors the TypeScript SDK’s guard rails so every release ships with the same signal quality (unit coverage, static analysis, spec parity, and synced fixtures). This guide explains how to run the suites locally, how CI enforces them, and where future contributors should extend coverage as new behaviour lands.
- Document the end-to-end testing workflow for this PHP client repository, including tooling, directory layout, and validation hooks.
- Record expectations for coverage, contracts sync, and parity scripts so regressions are obvious before release.
- Surface Mollie-inspired PHP testing ergonomics (PSR-18 mocks, reusable fixtures) that keep suites fast and deterministic.
- Call out backlog updates required now that the testing contract exists.
- Non-goal: Document feature behaviour-
docs/ARCHITECTURE.mdremains the source of truth for runtime design decisions.
| Suite / Check | Tooling | Status | Purpose |
|---|---|---|---|
| Unit | PHPUnit 11 (composer test) |
Available | Exercises core config, retry policies, HTTP adapters, and (eventually) domain facades using faked transports. |
| Integration | PHPUnit 11 (composer test -- --group integration) |
Planned | Hits the live Request API with PSR-18 clients (Guzzle recommended) once credential scaffolding lands. |
| Static analysis | PHPStan + Strict Rules (composer stan) |
Available | Enforces type safety across src/**. Mirrors TS pnpm typecheck. |
| Style / lint | PHPCS + Slevomat (composer cs, composer cs:fix) |
Available | Applies PSR-12 + strict import/type rules equivalent to the TS ESLint config. |
| Code health | PHPMD (composer md) |
Available | Flags complexity and dead code where PHPCS lacks coverage. |
| Coverage | PHPUnit TextUI (composer coverage) |
Available | Produces a line coverage summary. Thresholds will gate releases (≥80 % target). |
| OpenAPI parity | scripts/parity-openapi.php (composer parity:openapi) |
Available | Diffs implemented operationIds against the synced OpenAPI spec. |
| Webhook parity | scripts/parity-webhooks.php (composer parity:webhooks) |
Available | Diffs webhook event classes against the shared fixtures. |
| Contracts sync | scripts/sync-contracts.mjs (composer update:spec) |
Available | Copies OpenAPI + webhook assets from @marcohefti/request-network-api-contracts. |
| Path | Contents | Notes |
|---|---|---|
src/** |
Production code organised by domain (Config/, Http/, Retry/, etc.). |
PSR-4 root: RequestSuite\RequestPhpClient. |
tests/Unit/** |
PHPUnit unit suites. | Mirror TS folder names (e.g. Http, Retry) as new suites land. |
tests/Integration/** |
Placeholder for live suites. | Gate with PHPUnit groups to avoid accidental CI runs without credentials. |
tests/fixtures/** |
Planned PHP fixtures that wrap the shared JSON assets. | Prefer re-exporting @marcohefti/request-network-api-contracts fixtures. |
specs/** |
Synced OpenAPI & webhook specs + fixtures. | Populated by composer update:spec. Committed to VCS. |
scripts/** |
Node + PHP utilities (contracts sync, parity guards). | Keep scripts idempotent so CI re-runs stay green. |
- PHP ≥8.2 with
ext-json,ext-hash, andext-mbstringenabled (matchingcomposer.json). - Composer ≥2.7 with the
dealerdirect/phpcodesniffer-composer-installerplugin allowed:composer config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true - Coverage driver (Xdebug 3 or pcov) if you plan to run
composer coverage. - Node ≥20 (only required when you run the contracts sync script or other Node-based tooling). Install the dev dependency for contracts with:
npm install
- Install PHP dependencies:
composer install
| Command | Location | Description |
|---|---|---|
composer test |
repo root | Runs PHPUnit suites defined in phpunit.xml.dist. Use -- --filter RetryPolicyTest or -- --group integration for targeted runs. |
composer coverage |
repo root | Re-runs PHPUnit with --coverage-text. Requires Xdebug/pcov. Treat ≥80 % line coverage as the working floor. |
composer stan |
repo root | Executes PHPStan level 7 with strict rules. Mirrors TS pnpm typecheck. |
composer cs |
repo root | Runs PHPCS against src/**. |
composer cs:fix |
repo root | Applies PHPCS fixes (best-effort. Rerun composer cs afterwards). |
composer md |
repo root | Runs PHPMD (codesize, cleancode, unusedcode, naming) and reports any violations. |
composer update:spec |
repo root | Syncs OpenAPI + webhook specs/fixtures into specs/**. |
composer parity:openapi |
repo root | Fails if src/Validation/Operations.php drifts from the synced OpenAPI spec. |
composer parity:webhooks |
repo root | Fails if webhook event classes drift from synced fixtures. |
composer update:speccopies OpenAPI schemas (specs/openapi/**) and webhook assets (specs/webhooks/**,specs/fixtures/webhooks/**) from@marcohefti/request-network-api-contracts. The script writesspecs/meta.jsonwith SHA-256 fingerprints so we can detect drift in CI.composer parity:openapireads everyoperationIdin the synced OpenAPI spec and compares it to constants defined insrc/Validation/Operations.php. Missing IDs fail the build. Extra IDs mean PHP is ahead of the spec.composer parity:webhooksconverts fixture filenames (kebab-case) into PascalCase event names and compares them to classes undersrc/Webhooks/Events. Missing/extra events fail the run.UnknownEventis ignored to preserve a sane fallback.- Keep parity guards green before merging. If you intentionally add an allowlist, document it in this file and the backlog task so future work can remove it.
- Target ≥80 % line coverage across
src/**. Treat regressions below this floor as blockers. composer coverageprints the per-file summary. Pair it with PHPUnit’s HTML report (--coverage-html build/coverage) during investigations.phpunit.coverage.xml.distenforces the floor via<coverage><limit><line min="80"/></limit></coverage>. Document any temporary relaxation (e.g., during major refactors) in the task Execution Log.
In CI (and before publishing new releases), run at least:
composer csandcomposer stanfor style and static analysis.composer test(optionallycomposer coveragewhen a coverage driver is available).composer update:specto refresh contracts when needed.composer parity:openapiandcomposer parity:webhooksto enforce spec parity.
-
Follow the Mollie PHP SDK pattern: model transport behaviour behind a PSR-18 adapter so tests can swap in fakes without bespoke stubs.
-
Use the built-in
RequestSuite\RequestPhpClient\Testing\FakeHttpAdapterto queue responses, inspect capturedPendingRequests, and callassertSent/assertNothingSenthelpers instead of rolling custom mocks. Store reusable fixtures undertests/fixtures/**or reuse JSON fromspecs/fixtures/webhooks. -
Example harness:
use RequestSuite\RequestPhpClient\RequestClient; use RequestSuite\RequestPhpClient\Testing\FakeHttpAdapter; $fake = new FakeHttpAdapter([ FakeHttpAdapter::jsonResponse(['requestId' => 'req_fake']), ]); $client = RequestClient::create([ 'apiKey' => 'rk_test', 'httpAdapter' => $fake, ]); $client->requests()->create([...]); $fake->assertSent(static fn($pending) => $pending->method() === 'POST');
-
When integration suites arrive, default to Guzzle as the PSR-18 implementation. Inject via
RequestClient::create(['httpAdapter' => new Psr18Adapter(...)])and guard suites with PHPUnit groups/env checks. -
Prefer assertion helpers that mirror Mollie’s
assertSent/assertSentCountsemantics so contributors can verify headers, query params, and idempotency metadata without duplicating boilerplate.
- PHPUnit filters:
composer test -- --filter RetryPolicyTestruns a single class;-- --testsuite Unitforces the fast suite. - Toggle integration suites using
@group integrationannotations andcomposer test -- --group integration. - PHPStan auto-fixes aren’t available-address errors directly or annotate with
@phpstan-assertwhen narrowing types. - After syncing contracts, run
git statusto ensure new specs are committed (CI enforces a clean tree). - For large fixture updates, commit
specs/meta.jsonalongside the copied files so parity scripts can skip early.
- Composer plugin errors: re-run
composer installwithCOMPOSER_ALLOW_SUPERUSER=1and ensure the allow-list above is present. - Coverage driver missing: install
pecl install xdebugor enablepcov. PHPUnit 11 exits withCode coverage driver not available. - PHPStan memory issues: run
composer stan -- --memory-limit=1G. - Parity skips unexpectedly: confirm
specs/exists.composer update:specmust run before parity scripts can diff anything. - Node not found: ensure you ran
pnpm installfrom the repo root sonodeis available to the contracts sync script.
Track future testing-focused improvements (coverage thresholds, additional parity checks, dependency rules) in your own backlog or issue tracker so they are easy to prioritise alongside feature work.