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

Drift Laravel Package

pestphp/drift

Pest Drift is a Pest plugin for Laravel that detects database schema drift. It compares your migrations with the live database so tests fail when schema changes happen outside migrations, helping keep environments consistent and deployments predictable.

View on GitHub
Deep Wiki
Context7

Getting Started

First, resolve what this package actually is. The indexed description of pestphp/drift conflicts with its own repository: the blurb describes snapshot testing (expect()->toMatchSnapshot(), --update-snapshots), while the name, release notes ("Mark release with same version as pest"), and repo describe a PHPUnit→Pest codemod. Open composer.json, README.md, and src/ on the pinned tag before you run anything. If it's a snapshot library, this whole evaluation is void.

The ten-minute compatibility gate. This is a 2020 artifact built for the PHP 7.2/7.3 + Laravel 6/7 + Pest 0.x era. Do not attempt to composer require --dev it into a PHP 8.2+/Laravel 10+ application first — you will spend an afternoon fighting solver conflicts and learn nothing about the tool's usefulness. Instead:

# Throwaway workspace, not your app
composer create-project laravel/laravel:^7.0 drift-spike
cd drift-spike
composer require --dev pestphp/pest pestphp/drift:^0.3
ls vendor/bin   # confirm the actual binary name — do not guess it
vendor/bin/<binary> --help

If it won't resolve even here, the evaluation is over. Delete the directory.

Where to look first. In order: vendor/bin (real command name and flags), the package's src/ (what PHPUnit constructs it actually parses — look for ReflectionClass, @dataProvider, setUp), and its own test fixtures if present. The fixtures are the most honest documentation of supported surface area you will get, since there is no maintained docs site.

First use case: one file, not one suite. Copy a single, simple, assertion-only test class into the spike project's tests/Feature, convert it, and read the output. Your goal on the first run is not conversion — it's calibrating what "idiomatic Pest" means to a 2020-era tool so you can judge its output against the Pest version you actually intend to use. Only after that do you run it against a real directory, and when you do, pick the most syntactically varied directory you have, not the easiest one, or the conversion rate you measure will be fiction.

Keep phpunit.xml and the PHPUnit binary intact for the entire evaluation. You need both suites running in parallel to produce parity evidence.

Implementation Patterns

The spike workflow (the only defensible pattern). Drift is consume-once-and-discard, not a dependency:

  1. Branch off, never main. Better: do the conversion in a scratch clone and cherry-pick the output.
  2. Convert one directory at a time, committing each directory separately. Reviewable diffs are the whole game — a single 200-file diff guarantees rubber-stamping.
  3. Diff every converted file against its original by hand.
  4. Measure three numbers: files converted, converted files needing manual repair, repair minutes per file.
  5. Decide on evidence, then remove the tool from composer.json before merging.

Parallel-suite parity as your correctness oracle. Keep the PHPUnit tests running alongside the converted Pest tests and compare, per directory:

vendor/bin/phpunit --testdox > before.txt
vendor/bin/pest --testdox > after.txt
diff before.txt after.txt          # test names, data set names, skip markers
vendor/bin/phpunit --list-tests | wc -l
vendor/bin/pest --list-tests | wc -l

A shrinking test count is an obvious failure. Assertion count parity is the one that catches the dangerous case — a converted file that runs green with half the assertions. If you have PCOV or Xdebug available, generate per-file coverage for both runs and diff the coverage report; a converted file whose line coverage drops is a file that quietly stopped asserting something.

Lifecycle mapping. Expect setUp() to become beforeEach() and tearDown() to afterEach(). Two things to verify manually every time:

  • Scoping. A setUp() inherited from an abstract base class applies to every subclass; a beforeEach() pasted into one converted file applies to that file only. Push shared lifecycle into tests/Pest.php uses(...)->beforeEach(...) bindings so the scoping still matches.
  • parent::setUp() chains. A three-level inheritance tree flattens badly. Convert these by hand.

Data providers → datasets, with keys preserved. Named provider keys are part of your failure output; if the codemod drops them, every future failure becomes with data set #3 instead of with data set "admin user", and you will regret it for years. Check that generators, closure-based providers, and providers returning objects survive — these are the ones a small 2020 tool most likely mishandles.

Abstract base test classes and trait fixtures are your long tail. These have no mechanical Pest equivalent. The pattern that works: convert the concrete subclasses first, then hand-write the shared base as a trait or a Pest.php binding, then re-run the converted tests to confirm they still pass against the real fixture. Tests that pass only because the base class was silently dropped are the exact failure mode this tool is most likely to produce.

Dependency ordering. Convert leaf directories first (controllers, services), then directories whose tests depend on custom assertions or base classes, then mocking-heavy tests. Mocking is the one area where $this->mock() inside a Pest closure usually survives unchanged — but verify it rather than assume it.

Use it as a reference implementation, not a tool. The highest-value use of this codebase today is reading its parsing and rewrite logic to inform an internal Rector rule or a narrow regex script tailored to your suite's idioms. A ~40-line codemod that handles your three custom base classes is more valuable and vastly safer than a general-purpose 2020 tool that handles none of them. Same for comparing: if Pest's first-party migration tooling or a maintained Rector rule exists today, run both against the same directory — two days of comparison beats committing to either blind.

Gotchas and Tips

Silent semantic drift is the risk that should drive every decision here. A codemod that mis-translates a data provider, a @depends, a trait fixture, or a custom assertion produces tests that pass while asserting less than the original. Green CI is not evidence of correctness — it is evidence that the tests ran. This is invisible by construction, and it corrupts the artifact you rely on to ship safely. Budget review as a first-class line item: N converted files require N reviews, linearly, regardless of tool quality.

Do not leave it in require-dev. Archived since 2020, zero dependents, no CVE response, no PHP-version work. Even dev-only, it generates permanent composer audit / Dependabot / Snyk noise and will block or complicate every future PHP and Laravel upgrade. Consume once, then delete the line.

Composer resolution is the cheap kill test — run it first. Modern PHP constraints will likely require --ignore-platform-reqs or a fork with loosened constraints. If you do fork, pin to a commit SHA; the last tag is 2020-09-11 and will never track a PHP minor.

Output may not be idiomatic for the Pest you're migrating to. A 2020 tool emits 2020 Pest — test() vs it(), uses() placement, expectation API shape. Expect to hand-modernize syntax on top of hand-repairing semantics. That double pass is a real cost; factor it into your repair-minutes-per-file number.

expectException ordering is fragile. It must remain before the acting call. A rewrite that hoists the act above the expectation silently makes the test assert nothing about the exception.

@depends has no clean Pest equivalent. Convert these manually or restructure them — a mechanically converted @depends will either fail confusingly or, worse, run independently and pass for the wrong reason.

Don't stack it with a framework upgrade. Sequence this behind a go/no-go on the Pest migration itself and ahead of any test-suite restructuring. Running a test-framework codemod in the same window as a PHP or Laravel upgrade makes every failure unattributable and turns debugging into archaeology.

Debugging a converted file: run it in isolation with --filter, then re-run with --debug to confirm the dataset actually invoked. If a test "passes" suspiciously fast, it probably didn't run any assertions — check with coverage or by temporarily inserting a failing assertion.

Extension point, if you insist on going further: fork and add rules for your own base classes and custom assertions rather than patching output by hand. It's a small codebase — days, not weeks — but understand you're taking on permanent maintenance for one-time value. If nobody is named as owner, don't start.

And resolve the description conflict before spending engineering time at all. Two different products are documented for one package name. Mismatched marketing is itself a quality signal, and until someone confirms which it is, you are evaluating a guess.

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.
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
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect