pestphp/pest-plugin-phpstan
A Pest plugin that brings PHPStan static analysis into your Pest test suite, letting you run and assert PHPStan results directly from tests. Integrate type and error checks into your workflow without leaving Pest.
app/ but not tests/ is a common, silent split. This package is the enabler that lets you put a number on it: "our test suite is at PHPStan level 0 by default and level 8 in app/." That gap is a roadmap item, a definition-of-done change, or nothing — the plugin makes it cheap to find out which.expect() chains, wrong argument types passed to it()/dataset closures, unreachable assertions, broken custom expectations) is worth the added runtime and baseline churn.extension.neon, or simply excluding tests/ from analysis. This is a thin, MIT-licensed, removable integration — low lock-in, so it can be evaluated as a spike rather than a commitment.with([...])), custom expectations and Expectation extensions, beforeEach/use() trait wiring, and IDE/static feedback for engineers writing tests — meaningfully reduces the "tests are a second-class citizen" tax during onboarding and code review.phpstan.neon scaffold of your service template/repo starter, which turns a per-team debate into a one-time platform decision.Adopt when:
tests/, not just app/.beforeEach traits, or Pest's higher-order/fluent syntax that generic PHPStan stubs misread.Look elsewhere or defer when:
tests/ is near zero relative to the noise.Practical evaluation (one sprint, timeboxed):
tests/ at the current level, record the finding count and CI delta.To executives: This is a low-cost, low-risk quality-control addition to how we build software — it extends the same automated code checking we already run on our product code to cover our automated tests. The business case is narrow and honest: it prevents a class of silent failures where a test looks like it's protecting a feature but isn't, which is exactly the failure mode that lets defects reach customers. Cost is a few engineering hours and some additional CI time; the package is free, MIT-licensed, and can be removed in a single commit, so downside is bounded. Recommend a timeboxed trial with a measured result rather than a standing commitment.
To engineering: This teaches PHPStan about Pest's syntax so tests/ stops being an analysis blind spot. You get type checking and IDE support on expect() chains, dataset closures, and custom expectations — catching malformed assertions at CI time instead of at 3am in a flaky-suite investigation. It's a thin extension, not a framework, so treat it as configuration: pin it, verify it against our Pest and PHPStan versions, and be ready to drop it if a first-party integration covers the same ground. Success criterion is a measurable drop in test-suite defects and a clean PHPStan run at one level higher in tests/ than we have today — not "we installed a plugin."
How can I help you explore Laravel packages today?