dave-liddament/phpstan-rule-test-helper
A lightweight test helper for PHPStan custom rules. It provides utilities to run rules against sample code and assert expected errors, reducing boilerplate when validating your static analysis extensions.
Architecture fit. This is a dev-only testing utility for teams that author custom PHPStan rules. It sits one layer below Larastan: Larastan gives you Laravel-aware static analysis out of the box, but the moment you need to encode house conventions (ban env() outside config/, forbid Model::query() in controllers, enforce DTO immutability, restrict DB::raw()), you are writing your own PHPStan\Rules\Rule implementations — and those need tests. The package's value is entirely contingent on that precondition. For the median Laravel application, which consumes Larastan and writes zero custom rules, architecture fit is near-zero. For a platform team maintaining a shared rules package across multiple Laravel services, fit is moderate and real.
Integration feasibility. Low friction mechanically: composer require --dev, no service provider, no config publishing, no runtime surface. The genuine integration difficulty is not this package but the surrounding problem — rule tests under PHPStan's RuleTestCase analyze code in isolation, so rules that depend on Laravel container resolution, Eloquent model metadata, or facade roots typically need the application bootstrapped (via Larastan/Testbench) inside the test. This helper does not address that; it reduces boilerplate around fixtures and assertions, not around framework context.
Technical risk.
RuleTestCase and PHPStan's analysis/error API, which have shifted across 1.x → 2.x. Breakage is likely at major bumps.Key questions.
Stack fit. Composer/PHP 8.x/PHPStan 1.x–2.x/PHPUnit 10–11. Require as require-dev only, co-located with the rules package (tools/phpstan-rules or packages/standards) rather than in each application — this keeps the dependency out of every service's lockfile and centralizes the upgrade.
Migration path. There is nothing to migrate from on day one; existing custom rules already have either (a) hand-rolled RuleTestCase subclasses with on-disk fixtures, or (b) no tests. Path is additive: wrap the helper in an internal BaseRuleTestCase that (i) supplies Larastan's bootstrap config, (ii) enforces an explicit expected-error-count argument, and (iii) fails when zero errors are asserted. That thin internal seam is what converts a 1-star dependency into a stable internal API and makes it replaceable if the package stalls.
Compatibility. Verify against the exact PHPStan major pinned in your CI matrix before rollout; do not allow the helper to float across a PHPStan major. Confirm interaction with Larastan's own extension of the analysis config — conflicting getAdditionalConfigFiles() implementations are the most likely integration snag. Also confirm the rules package itself is not required at runtime by any service; it should be a dev/tooling artifact only.
Sequencing.
Maintenance. Single maintainer, no vendor, no SLA. Treat as a convenience wrapper, not infrastructure: budget for a fork (the codebase is small enough to vendor into the internal tools repo outright) or a fallback to PHPStan's native RuleTestCase. Pin the version; upgrade deliberately alongside PHPStan major bumps, not on composer update.
Support. Community issues only. Internal ownership must be assigned to whoever owns the standards/rules package — this is a tooling-team dependency, not an app-team one. If no team owns custom PHPStan rules, there is no owner for this package either, and that is the signal to decline adoption.
Scaling. No production scaling implications whatsoever — zero runtime footprint, no dependents, no autoload cost in deployed artifacts. The only scaling dimension is CI: each rule test triggers a full PHPStan analysis pass, typically low seconds per case. At dozens of rules × multiple cases this becomes a meaningful slice of CI wall-clock; mitigate with Paratest sharding and by scoping rule tests to a separate CI job that runs only when the rules package changes (path filters). Keep the runtime suite untouched by design.
Failure modes.
RuleTestCase per test without rewriting fixtures if you keep fixtures as strings.Ramp-up. Hours, not days, for an engineer already comfortable with PHPStan's AST/Scope model — the helper only removes fixture plumbing. The real learning curve is the rules themselves, which this package does not shorten. For a team with no custom-rule practice, the total cost of entry (learn PHPStan rule internals + adopt an unvetted dev dependency) far exceeds the payoff at 1 star and 0 dependents; the recommendation there is to skip and rely on Larastan plus PHP-CS-Fixer. Where a standards package already exists, the opportunity score is justified: cheap adoption, contained risk, and a measurable drop in rule-test boilerplate.
How can I help you explore Laravel packages today?