pestphp/pest-plugin-global-assertions
A Pest plugin that adds global assertion helpers like assertTrue(), assertEquals(), and assertSame() to your test suite, bringing familiar PHPUnit-style assertion functions to Pest tests without extra imports or setup.
Architecture fit. Global Assertions is a dev-only Pest plugin that registers reusable custom assertions suite-wide. Its entire footprint is the test layer: no service provider, no published config, no runtime code, no production coupling. For a TPM the correct framing is that this is a test-authoring standard, not a platform dependency — it either raises the readability and reviewability of tests across packages, or it is noise. It earns its place only when the same domain checks (toBeRefundable, assertWithinSla, assertValidTaxId) are currently copy-pasted across many files. The structural hazard is inherent to the feature: a global registry is cross-cutting by construction, and without naming conventions, an owner, and review discipline it becomes an implicit contract every suite silently depends on.
Integration feasibility. High and cheap. Composer-installable into require-dev, auto-discovered via extra.pest.plugins, assertions declared once in tests/Pest.php. No migration, no data changes, no service wiring; removal is an afternoon of work. Feasibility is therefore gated almost entirely on compatibility and maturity signals — Pest major, PHPUnit major, PHP version, and behaviour under parallel testing — not on engineering effort. That asymmetry (trivial to adopt, non-trivial to trust) is the core of the decision.
Technical risk. Dominant risks are maturity and bus factor, not correctness: 7 stars, 0 dependents, single-maintainer signals, no visible CI compatibility matrix, no field validation. Specific hazards to spike before it becomes load-bearing:
Pest.php files.RefreshDatabase) and pest --parallel.Blast radius is contained to CI runtime and developer workflow; a broken test plugin never reaches a customer. That containment is what makes this a cheap, reversible experiment rather than a governance event — and also why it should never enter a production-architecture discussion.
Key questions.
pest --parallel and with RefreshDatabase?expect()->extend() in tests/Pest.php?expect()->extend() plus a shared bootstrap file does not? If not, the TPM answer is no.Stack fit. Strong only where the org already runs Pest across multiple packages or squads and has a genuine library of reused assertions (rule of thumb: three or more assertions duplicated across three or more files). Weak or wrong where the suite is PHPUnit-only (a base TestCase or trait is idiomatic), where the need is a handful of single-file helpers, or where dependency governance requires demonstrated adoption — 7 stars and 0 dependents will not clear a strict supply-chain review, and convenience is not worth an exception. It has zero runtime footprint and none of its risks are customer-facing.
Migration path. Time-boxed, reversible, one package at a time. Inventory existing custom expectations and duplicated helper closures; map the subset that should become global (cross-cutting policy, not one-file conveniences); pilot in a single non-critical module on a pinned version; measure duplicated-helper reduction and reviewer feedback against a baseline captured before the pilot; then either standardise with an internal guide and template, or exit by folding the assertions into a trait. Document the exit path before the pilot starts — that is what makes "we can fold this into a local trait" an honest statement rather than an aspiration.
Compatibility. Pin the exact version in composer.lock, keep it strictly in require-dev, and run CI against the oldest and newest Pest/PHP combinations in the support window. Exercise parallel execution, test-database refresh, and dependency caching during the pilot. Treat the plugin's Pest-major support as an explicit input to any framework upgrade plan: an unmaintained dev dependency that breaks on a Pest v2→v3 bump converts a code annoyance into a roadmap blocker for the entire upgrade, so track it on the platform backlog from day one rather than discovering it mid-migration.
Sequencing.
vendor/pestphp/pest-plugin-global-assertions/src as the de facto documentation — the README does not fully describe the registration signature, $this binding, or return-value contract.require-dev only, version pinned.expect()->extend() + tests/Pest.php alternative on the same measurements, not on aesthetics.Maintenance. Low code footprint and low maintenance effort, but not zero maintenance risk. Assign an explicit internal owner to track upstream releases and Pest upgrades. If adoption spreads across many packages, evaluate vendoring or forking under MIT to neutralise abandonment risk — the licence makes that a genuinely viable hedge. Keep it categorised as a convenience layer over primitives the team could reproduce in an afternoon, never as critical test infrastructure. The realistic failure is not that the code rots, but that nobody notices it has rotted until an upgrade forces the question.
Support. Expect effectively no external support; internal documentation is load-bearing. The essential artefacts are worked examples, naming standards, a short guide to reading global-assertion failure output, and — most importantly — editorial guidance on when to write a global assertion versus a local expectation. Without that guidance the registry becomes an unowned dumping ground within roughly two quarters, at which point it is a liability with a plugin dependency attached.
Scaling. Scales well when it centralises genuinely shared domain rules and enforces naming consistency across many suites; scales badly when assertions proliferate unreviewed. Failure at scale presents as name collisions, unclear ownership of individual assertions, hidden cross-suite coupling (changing one assertion silently alters dozens of unrelated suites), and reviewers unable to trace where an assertion came from or who owns it. Mitigate with a maintained catalogue, mandatory PR review for new assertions, and a soft size ceiling on the registry.
Failure modes. Plugin load failure in the Pest bootstrap; version drift after a Pest/PHPUnit upgrade; assertion-name collisions with core expectations or other plugins; silent semantic changes in a release; weak failure diagnostics that slow triage. Each is contained to CI and developer workflow but can block a framework upgrade if the plugin is load-bearing. Mitigations: pinned version, CI compatibility matrix, a smoke test that asserts one global assertion fires and fails as expected, and a pre-agreed exit path.
Ramp-up. Small. Developers need one worked example to become productive; the real cost is editorial, not technical. Expect roughly a sprint to pilot, a short internal guide, and a single owner for the upgrade watch item. The main ramp-up risk is philosophical drift — engineers discovering expect()->extend() afterwards and asking, legitimately, why a third-party dependency exists for the same capability. Have the answer ready at adoption, not after.
How can I help you explore Laravel packages today?