The Daily Commit · Section Edition Front Page PHP AI Dev EN DE FR ES

The Php Times

Reads — Ecosystem

Pest 5 arrives with Test Impact Analysis, AI agent tooling, and eval support


Nuno Maduro announced Pest 5 at Laracon US 2026.

LARAVEL NEWS, July 29, 2026 curated by Sönke

The release brings a Test Impact Analysis engine that cut Laravel Cloud's 19,000-test suite from 3 minutes to 5 seconds, plus plugins for AI agent verification, LLM evals, PHPStan, and Rector. PHP 8.4 and PHPUnit 13 are the new baseline.

Nuno Maduro announced Pest 5 on stage at Laracon US 2026 in Boston and tagged v5.0.0 during the conference. The new major version of the PHP testing framework requires PHP 8.4 and runs on PHPUnit 13.

The headline feature is the Tia (Test Impact Analysis) engine. On its first run it records which tests touch which files; afterwards, invoking `./vendor/bin/pest --parallel --tia` executes only the tests affected by your changes and replays cached results for the rest. Laravel Cloud's suite of over 19,000 tests reportedly dropped from 3 minutes to 5 seconds. Cached results retain full line and branch coverage data, so `--coverage` reports and `--min` thresholds behave as if the whole suite ran. The dependency graph goes beyond PHP: changing a migration re-runs tests that queried that table, editing a shared JS component follows Vite's module graph to affected Inertia pages, and touching a Blade template re-runs the tests that rendered it. Laravel, Symfony, Livewire, Inertia, and browser assets are detected automatically via Composer. Files are normalized before hashing (whitespace, comments, and docblocks stripped), so a Pint pass triggers no re-runs. Recording the baseline requires PCOV or Xdebug; CI can record the baseline once per merge to main for others to download, though baseline sharing requires an authenticated GitHub CLI and works only on GitHub. Behavior is configured in tests/Pest.php via `pest()->tia()` with methods like `always()`, `locally()`, `baselined()`, and `filtered()`.

The Agent plugin (pestphp/pest-plugin-agent) gives AI coding agents a way to verify changes. Its `--agent` option runs a snippet as an isolated test named "verify" with factories, RefreshDatabase, and Laravel fakes available, e.g. creating a user and asserting a dashboard request returns OK. With the browser testing plugin installed, probes can drive a real browser and assert backend side effects. It is positioned as quick feedback, not a replacement for committed regression tests.

The Evals plugin (pestphp/pest-plugin-evals) addresses non-deterministic LLM output by scoring quality instead of asserting equality, using the familiar expect() API. Evals call real models, so they are skipped on normal runs and only execute with `--evals`. Deterministic expectations like toContain(), toMatch(), toBe(), and toBeJson() need no driver. Scored expectations accept a threshold from 0.0 to 1.0 (default 0.7): toBeRelevant(), toBeSafe(), toBeFactual(), toBeSimilar(), and toPassJudge() for plain-English criteria, plus toHaveToolCalls() and toFollowTrajectory() for agent tool usage, repeat() for sampling, and toPassScorer() for custom scorers. Scoring runs through Laravel AI by default, with judge and embeddings drivers swappable via closures or custom classes.

First-party PHPStan support (pestphp/pest-plugin-phpstan) was a long-requested feature. The plugin reads Pest.php to determine what $this is inside test closures, supporting both uses(TestCase::class)->in(...) and pest()->extend(...) styles, and self-registers with phpstan/extension-installer. Types flow through expectation chains, toBeInt() narrows unions, beforeEach() properties are typed, and impossible expectations like expect(10)->toStartWith('1') are flagged. Additional Pest-aware rules cover static closures, $this in beforeAll(), duplicate descriptions, and invalid throws()/covers() references, each with stable identifiers like pest.expectation.impossible.

The Rector plugin (pestphp/pest-plugin-rector) ships 60 rules across coding-style and version-upgrade sets. The style set rewrites raw PHP assertions as matchers (e.g. combining count and key checks into toHaveCount(5)->toHaveKey('id')), converts PHPUnit assertions to expect(), and turns try/catch exception tests into toThrow(). Upgrade sets under PestLevelSetList are cumulative; preview with --dry-run.

Time-balanced sharding, introduced in Pest v4.6.0, distributes CI shards by recorded runtime rather than file count: record timings with --update-shards, commit tests/.pest/shards.json, and --shard=1/4 picks it up automatically.

Eight new expectations handle tedious format checks: toBeEmail(), toBeUlid(), toBeIpAddress(), toBeMacAddress(), toBeHostname(), toBeDomain(), toBeBase64(), and toBeHexadecimal(), each with optional custom failure messages and negation via not.

Upgrading means bumping pestphp/pest and Pest-maintained plugins to ^5.0 in composer.json. The upgrade guide estimates about two minutes with no API-level breaking changes beyond the version bumps; most friction will come from PHPUnit 13 itself.

Read the original source ↗

Rate this article: 0

Readers’ Forum

No contributions yet — open the debate.

← Ecosystem — Page B1

"All the Code That's Fit to Ship" · The Daily Commit · Screen edition · Imprint · Privacy Policy