Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rector Phpunit Laravel Package

rector/rector-phpunit

Rector rules for PHPUnit that automate test suite upgrades. Modernize assertions, replace deprecated APIs, and keep tests compatible across PHPUnit versions through automated, configurable refactoring—no manual edits required.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. rector/rector-phpunit is not runtime code — it is a ruleset plugin for Rector (the AST-based PHP refactoring engine) that automates PHPUnit major-version migrations. Architecturally this is a dev-tooling dependency with zero production footprint: it lives in require-dev, never ships to the app, and cannot affect request handling, container bindings, or Laravel bootstrapping. It plugs in as a config entry in rector.php (e.g. PHPUnitLevelSetList::UP_TO_PHPUNIT_110) and operates only on the paths you scope. For a Laravel codebase this fits cleanly because Laravel's test layer is conventional PHPUnit — standard TestCase subclasses, standard assertions — which is exactly the surface these rules target.

Integration feasibility. High and low-cost. The package is first-party within the rectorphp GitHub org, versioned in lockstep with Rector releases, and is the ruleset Rector's own documentation points to. Installation is a single composer require --dev plus a config block; the first useful output (a diff) is available within minutes via --dry-run. The real feasibility question is not "can we install it" but "how much of our suite is idiomatic enough for the rules to cover."

Technical risk. Contained. Every change lands in version control as a reviewable diff, is reversible with git checkout, and is validated by the test suite itself — the rare tooling category where the artifact under change is also its own verification. The genuine risks are subtler:

  • Semantic drift in assertions. A rule may rewrite an assertion such that it still passes but tests something marginally different. Dry-run review is mandatory, not optional.
  • Partial transformation. Rules cover common removals (assertRegExp → assertMatchesRegularExpression, setUp(): void, @dataProvider → #[DataProvider]), but custom constraints, mocked removed methods, and bespoke base-class helpers will be left untouched and must be fixed by hand.
  • Version skew. Rector and Rector PHPUnit have coupled major versions; mismatches produce silent no-ops rather than errors, creating false confidence that a migration is complete.
  • Pest incompatibility. Pest wraps PHPUnit with different annotation/attribute conventions; rules may skip or mis-handle Pest-style tests.
  • Ecosystem signals are thin. 117 stars and 0 listed dependents is weak independent-adoption evidence — but the first-party org affiliation matters more than the star count, and the dependent metric undercounts dev-only tooling.

Key questions.

  1. Which PHPUnit jump(s) are we actually taking, and is it one major or several?
  2. What Rector major is compatible with our PHP floor (PHPUnit 10+ attributes require PHP 8.1)?
  3. How much of our suite is Pest vs. PHPUnit, and does the PHPUnit portion share custom base classes or traits the rules cannot see?
  4. Is our suite green before we start, so we can distinguish pre-existing failures from tool-induced ones?
  5. Do we want this as a one-time migration aid or a standing CI guard against regressions?
  6. What is the manual-remediation budget if coverage is, say, 80% of call sites?

Integration Approach

Stack fit. Native Composer/vendor/bin fit with no framework coupling. Configuration is a single rector.php at repo root; we scope withPaths() to tests/ plus any test-support directories to prevent Rector from touching application code. Runtime is developer machines and CI only — no effect on deploy artifacts, image size, or boot time.

Migration path. Branch-based, staged, reversible:

  1. Baseline. Lock dependencies, run the full suite, record the green state and any pre-existing skips/failures.
  2. Bump PHPUnit in composer.json first, install, and let the suite break. This defines the true blast radius.
  3. Dry run. vendor/bin/rector process tests/ --dry-run to size the diff and eyeball rule coverage before committing to anything.
  4. Apply in batches — tests/Unit first (usually highest rule coverage, lowest custom-helper density), then tests/Feature, then shared test scaffolding.
  5. Manual remediation for the tail: custom constraints, mock expectations on removed methods, attribute conversions the rules skipped.
  6. Verify with the same full-suite run from step 1 and compare failure sets.

Compatibility. Pin rector/rector and rector/rector-phpunit to matching majors and commit both to composer.lock. Rector has meaningful BC breaks between its own majors, so the Rector upgrade cadence — not the PHPUnit ruleset — is the recurring compatibility cost. Check that no first-party package in the dependency tree pins PHPUnit below the target version, and confirm PHP version satisfies both the new PHPUnit and the chosen Rector major.

Sequencing. The dependency order is fixed: lock/baseline → PHPUnit bump → Rector dry-run → batched application → manual tail → full-suite verification → merge. CI enforcement (Rector in --dry-run/check mode on PRs) should be a later, optional phase, not part of the initial migration — adding a guard before the codebase is clean will just produce noise.

Operational Impact

Maintenance. The package is actively maintained by the Rector core team and gains rulesets as PHPUnit ships majors — we inherit that work for free. Our own maintenance burden is version pinning plus a config edit per upgrade cycle, measured in minutes. The larger, less obvious cost is Rector itself: Rector majors introduce breaking config and rule changes, so adopting this package effectively enrolls us in Rector's upgrade cadence whether or not we ever migrate PHPUnit again.

Support. MIT, community-driven, GitHub issues only, no vendor SLA. The practical escalation path for hard cases is a paid migration service (Laravel Shift or a consultant) rather than package support. Rector's documentation is genuinely good, which materially lowers the support burden.

Scaling. CPU- and memory-intensive on large suites — Rector parses the full AST of every in-scope file. Mitigations are straightforward: scope to tests/, use Rector's parallel processing, and run it in CI rather than on developer machines. Because it is dev-only, there is no production scaling consideration whatsoever.

Failure modes. Ranked by likelihood and severity:

Failure Likelihood Impact Mitigation
Rule silently no-ops due to version skew Medium High (false confidence) Pin matched majors; review diff volume against expectation
Assertion rewritten with changed semantics Low–Medium High (tests pass but test less) Mandatory human diff review
Partial transform leaves broken test file Medium Low (CI catches) Batched application + suite run per batch
Memory exhaustion on large suite Medium Low Scope paths, run in CI, chunk by directory
Pest tests skipped without warning Medium if Pest present Medium Inventory Pest files separately; handle manually
Rector touches non-test code Low Medium Explicit withPaths() scoping

Ramp-up. Low. Engineers unfamiliar with Rector need roughly half a day to read the config, run a dry-run, and interpret the diff confidently; those who have used Rector need essentially none. The migration itself is a one-to-two-day effort for a mid-size Laravel application, dominated by manual remediation of the tail rather than by tool operation. Budget more if Pest is in play or if the suite leans heavily on custom test helpers.

Bottom line for the decision. Low-risk, low-cost, reversible dev-tooling with a clear one-time payoff and a modest recurring cadence cost inherited from Rector. The adoption signals are thin in absolute terms, but first-party org status substitutes for them. The decision hinges on whether a PHPUnit major upgrade is on the roadmap — if it is, this is straightforwardly worth piloting on a branch and measuring rule coverage before committing.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource