Product Decisions This Supports
- Build vs. buy for test infrastructure. Teams adopting event sourcing inevitably write their own test harness around aggregates (fixture setup, command dispatch, event assertions, subscriber lifecycle). This package productizes that harness as a dev-only dependency — the PM decision is whether to spend engineering days reinventing it versus
composer require --dev.
- Committing to event sourcing as an architecture. Adopting the testing companion signals and enables a deeper investment in DDD/CQRS. It is the difference between "we have aggregates but nobody tests state transitions" and "every aggregate has a readable behavioural spec" — which is what makes event-sourced systems maintainable over years.
- Test strategy and quality gates. It standardises a given/when/then convention across the domain layer, which makes domain tests reviewable by non-authors, useful as living documentation for product rules (order lifecycle, pricing, entitlements, approval flows), and cheap to extend when rules change. The maintainers' mutation-testing badge is a signal you can hold this dependency to a quality bar.
- Roadmap sequencing. If the roadmap includes audit trails, temporal queries, or "what did this entity look like on date X" features, event sourcing becomes a candidate architecture; this package should be scoped into the same initiative, not bolted on later. Conversely, if the roadmap is CRUD-heavy with simple state, this is a signal not to go down the event-sourcing path.
- Ecosystem standardisation. Choosing the
patchlevel core + PHPUnit companion as a pair is a bundling decision — a coherent, single-vendor toolchain for event sourcing in PHP versus assembling Spatie/EventSauce/Prooph plus bespoke test code.
- Onboarding and developer experience. Readable behavioural tests lower the ramp for new engineers joining a domain-heavy codebase; the PM can use this as a concrete retention/velocity lever on complex teams rather than an abstract "improve testing" aspiration.
- Refactor safety for high-value logic. Where a bug in domain logic costs real money (billing, fulfilment, compliance), the ability to refactor aggregates against a GWT spec suite is a risk-reduction decision, not a tooling preference.
When to Consider This Package
Consider it when:
- You are already on, or actively evaluating,
patchlevel/event-sourcing — this is effectively a first-party companion and adds no conceptual overhead.
- Domain logic has genuine state machines and business rules worth specifying (orders, subscriptions, ledgers, workflows) rather than thin CRUD.
- Your stack is PHP with PHPUnit already in place; the package is a dev dependency and does not affect production runtime or deployment size.
- You want the command-dispatch path (
#[Handle] methods) exercised in tests, not just aggregate methods called directly — i.e. you care about testing the seam your application actually uses.
- You are willing to accept a small, single-maintainer ecosystem and mitigate with version pinning, a fork-ready posture, and at least one engineer who understands the internals.
Look elsewhere (or skip it) when:
- You are not doing event sourcing. This has no value as a general testing utility.
- You are on a different event-sourcing library (Spatie, EventSauce, Prooph, Broadway) — the abstractions will not line up, and each of those has its own testing story.
- You need enterprise support contracts, an SLA, or a large hiring pool of engineers who already know the API. Adoption is essentially zero (1 star, 0 dependents), so community answers and third-party tutorials will be scarce.
- Your team's convention is plain PHPUnit with hand-rolled fixtures and you value uniformity over notation ergonomics — the abstraction is small, but it is still an abstraction to teach.
- The scope is a short-lived prototype where writing a few fixture helpers is a couple of hours of work and a dependency carries more governance cost than it saves.
- You require long-term vendor stability guarantees; this should be treated as a "pin the minor version and read the changelog" dependency.
How to Pitch It (Stakeholders)
For executives (30 seconds): This is a free, MIT-licensed, development-only add-on that makes our domain logic testable in plain business language — "given this history, when this happens, then this is true." It costs nothing at runtime, ships nothing to customers, and reduces the cost of getting billing/order/workflow rules wrong, which is where bugs are most expensive and hardest to unwind. The trade-off is that it comes from a very small open-source project, so we pin the version and keep the option to fork, which is a day of work at most.
For engineering leads: It removes the boilerplate tax on event-sourced tests. You get a given/when/then base case, a when that dispatches through your real #[Handle] command methods rather than calling aggregate methods directly, closure-based state assertions instead of brittle event-list diffs, and a subscriber setup/run/teardown utility. That means tests exercise the same path production does, reviews are readable by people who do not know the aggregate internals, and the suite doubles as documentation of product rules. The project is mutation-tested, which is more than most dev tooling can claim.
Framing the risk honestly: Low stars and zero dependents is a real signal — no community safety net, no Stack Overflow trail. Position it as a dev-only, version-pinned, fork-able convenience layer rather than a platform commitment. The cost of removal is small (delete the package, keep the tests conceptually), which is exactly the profile of a dependency worth trialling on one bounded context before rolling it across the domain.