Modern Browser Testing and Sharding with Pest 4
Overview of Pest 4 Capabilities
Pest 4 represents a massive shift in how PHP developers approach end-to-end testing. Historically, browser testing in the Laravel ecosystem relied on Laravel Dusk, which often felt slow or difficult to debug in CI environments. Nuno Maduro has rebuilt the browser testing experience on top of Playwright, the industry standard for high-performance automation. This update brings lightning-fast execution, parallelization, and a suite of high-level assertions that make testing feel like an extension of unit testing rather than a separate, clunky chore.
Prerequisites and Environment Setup
To follow this tutorial, you should have a solid grasp of PHP 8.2+ and Laravel fundamentals. Since the new browser testing engine utilizes Playwright, you will need Node.js installed to handle the underlying browser drivers. You should also be comfortable running terminal commands and managing a standard Laravel testing environment with SQLite.
Key Libraries & Tools
- Pest 4: The core testing framework for PHP.
- Playwright: The high-performance engine driving the browser interactions.
- Laravel: The application framework used for the live examples.
- Inertia.js: Used in the demo to show how Pest 4 handles React and JavaScript heavy front-ends.
Browser Testing Walkthrough
The syntax for browser testing in Pest 4 is remarkably clean. Instead of the standard get() request used in feature tests, you use visit(). This triggers the Playwright engine to render the page fully.
test('user can login', function () {
$user = User::factory()->create();
$this->visit('/')
->click('Login')
->type('email', $user->email)
->type('password', 'password')
->press('Login')
->assertSee('Dashboard');
});
One of the most impressive features is the shared memory state. In older tools, your browser and your test run in separate processes, making it hard to use RefreshDatabase. Pest 4 allows you to use SQLite in-memory across both the test and the browser, drastically increasing speed. Furthermore, you can mix unit testing helpers directly with browser actions. For instance, you can use Notification::fake() and then verify a notification was sent after a browser click—all within the same test block.
Advanced Debugging and Visual Diffs
Debugging browser tests has historically been a "guess and check" process. Pest 4 introduces the debug() and tinker() methods to stop this cycle. Placing ->debug() before a failing assertion pauses the test and focuses the browser window so you can see exactly what is wrong. The ->tinker() method is even more powerful; it opens a Laravel Tinker session at the exact moment of execution, allowing you to inspect the backend database state or the currently authenticated user.
Visual Regression Testing
Visual testing is now a first-class citizen. By calling assertScreenshotMatches(), Pest PHP captures a baseline image. On subsequent runs, it compares the current UI against that baseline.
test('homepage visual regression', function () {
$this->visit('/')
->assertScreenshotMatches();
});
If a single pixel is out of place due to a CSS change, the test fails. You can run the test with the --diff flag to open a side-by-side slider in the browser, showing exactly what changed in red.
Syntax Notes and Modern Features
Pest 4 leans heavily into fluent chaining and "smoke testing" shortcuts. The assertNoSmoke() method is a powerful shorthand that automatically visits all routes in your application and asserts that there are no JavaScript errors and no console.log statements left behind.
Another syntax feature is the device configuration. You can easily test how your site looks on different viewports by chaining methods like onMobile() or specifying exact hardware like onIphone15(). You can even toggle onDarkMode() to ensure your CSS variables are rendering correctly across themes.
Sharding for GitHub Actions
As test suites grow, execution time often becomes a bottleneck. Pest 4 introduces sharding to solve this. Instead of one long 10-minute run, you can split your suite into smaller chunks across multiple GitHub Actions runners. By adding the --shard=1/5 flag, you tell Pest PHP to only run a specific fifth of the tests. When combined with GitHub matrices, this can reduce a 10-minute CI process down to just 2 minutes without changing a single line of test code.
Tips & Gotchas
- Database Isolation: Always use the
RefreshDatabasetrait when testing browser flows that modify data. Because Pest 4 shares the connection, your database state stays in sync. - Automatic Waiting: You no longer need to manually code
waitForText(). Pest PHP automatically waits for redirects and element visibility, reducing flakiness. - Parallel Execution: Use the
--parallelflag locally to maximize your CPU cores. Pest PHP and Playwright both support parallel execution, often making browser tests run five times faster than sequential Laravel Dusk runs.
- Pest 4
- 27%· products
- Playwright
- 15%· libraries
- Laravel
- 12%· frameworks
- Pest PHP
- 12%· products
- PHP
- 9%· programming languages
- Other topics
- 24%

Pest 4: Modern Browser Testing, Sharding, Visual Diffs & more | Nuno Maduro at Laracon US 2025
WatchLaravel // 29:49
The official YouTube channel of Laravel, the clean stack for Artisans and agents. We will update you on what's new in the world of Laravel, from the framework to our products Cloud, Forge, and Nightwatch.