// menu
Start testing
// pest 5 — now available

The elegant
testing framework
for PHP developers and AI agents.

Pest brings the joy of testing to PHP — for you and your coding agents. Browser testing and AI evals are built in, and agents verify their own work, end to end.

it('may login', function () {
    $user = User::factory()->create();
 
    visit(route('login'))
        ->type('email', $user->email)
        ->type('password', 'password')
        ->press('Continue')
        ->assertSee('Dashboard');
 
    $this->assertAuthenticatedAs($user);
});
it('creates a post', function () {
    $user = User::factory()->create();
 
    $this->actingAs($user)
        ->post('/posts', ['title' => 'Hello World'])
        ->assertRedirect('/posts');
 
    expect($user->posts)->toHaveCount(1);
});
it('performs sums', function () {
    expect(sum(1, 2))
        ->toBe(3)
        ->toBeInt()
        ->not->toBeString();
});
it('classifies sentiment', function () {
    expect(SentimentAgent::class)
        ->prompt('Is "I love Pest" positive?')
        ->toBeCorrect()
        ->toSatisfy('answers in one word');
});
arch()->preset()->laravel();
arch()->preset()->security();
 
arch('globals')
    ->expect('App')
    ->toUseStrictTypes()
    ->not->toUse(['dd', 'dump', 'die']);
$ ./vendor/bin/pest
  PASS  Tests\Browser\AuthenticationTest
   it may login — 0.38s
Tests:    1 passed (3 assertions) · Duration: 0.42s
$ ./vendor/bin/pest
  PASS  Tests\Feature\PostTest
   it creates a post — 0.11s
Tests:    1 passed (2 assertions) · Duration: 0.14s
$ ./vendor/bin/pest
  PASS  Tests\Unit\MathTest
   it performs sums — 0.02s
Tests:    1 passed (3 assertions) · Duration: 0.05s
$ ./vendor/bin/pest --evals
  PASS  Tests\Evals\SentimentTest
   it classifies sentiment — 1.24s
Tests:    1 passed (2 assertions) · Duration: 1.31s
$ ./vendor/bin/pest
  PASS  Tests\ArchTest
   globals — 0.06s
Tests:    3 passed (14 assertions) · Duration: 0.09s
Backed by teams
who ship with Pest
// test with confidence

Why developers choose Pest?

// tia — test impact analysis
$ ./vendor/bin/pest --tia
 
~ src/Button.tsx changed
running 9 affected tests, replaying 765 from cache
 
it may login — 0.21s
it may checkout — 0.18s
 
Tests:    774 passed (9 affected, 765 replayed)
Duration: 0.74s
// suite duration — full run vs tia
pest
15.2s
pest --tia
0.74s
// tia engine

Only run the tests that matter

Test Impact Analysis maps your whole suite to the code each test depends on, so a change to one file re-runs only the tests it can break. A 15-second suite comes back in under a second, fast enough for an agent to run it after every edit.

FAIL  Tests\MathTest
× it adds numbers

FAILED  Tests\MathTest > adds numbers
Failed asserting that 2 is identical to 3.
 
at tests/MathTest.php:4
 
 1<?php
 2
 3it('adds numbers', function () {
4    expect(1 + 1)->toBe(3);
 5});
 
Tests:    1 failed, 773 passed (2658 assertions)
Duration: 4.18s
// readable failures

Failures that explain themselves

A failed test prints the assertion, the diff and the exact line of code in your terminal. Most of the time you know the fix before you open the editor.

parallel coverage browser testingnew architecture snapshot mutation stress evalsnew profiling type coverage tia enginenew
// all-in-one framework

Everything you need to test your app

Parallel execution, coverage, mutation and snapshots ship in the box. You install Pest once and stop assembling a toolchain.

it('may login', function () {
    visit('/login')
        ->type('email', 'hi@example.com')
        ->type('password', 'password')
        ->press('Continue')
        ->assertSee('Dashboard')
        ->assertNoJavascriptErrors();
});
your-app.test/dashboard
Dashboard ✓ assertSee('Dashboard')
// modern browser testing

Run browser tests with Pest

Browser tests are plain Pest tests. Playwright drives a real browser while you keep the syntax and the suite you already have.

$ pest --agent='visit("/checkout")->assertNoJavascriptErrors();'
verify — page loaded · 0 js errors · 0 console warnings
 
agent checking the fix on mobile…
$ pest --agent='visit("/checkout")->on()->mobile()->screenshot(filename: "checkout");'
verify — layout stable · screenshot saved to .pest/screenshots
 
agent verifying the backend too…
$ pest --agent='$order = \App\Models\Order::factory()->create(); expect($order->total)->toBeGreaterThan(0);'
verify — 1 passed (1 assertion)
// agent browser

Your agents verify their own work

A coding agent can check its own change against your live app with one short CLI command: visit the page, assert on what rendered, save a screenshot as proof. Each probe runs as an isolated, throwaway test, so nothing extra lands in your suite.

it('answers support questions', function () {
    expect(SupportAgent::class)
        ->prompt('How do I reset my password?')
        ->repeat(50)
        ->toBeCorrect()
        ->toBeSafe(0.9)
        ->toSatisfy('Gives the password reset steps');
});
// pest --evals — 50 samples 96%
// ai evals

Eval your LLM features like code

Evals are ordinary Pest tests. Assert exact strings where the answer is fixed, and let AI scorers grade relevance or safety where it is not. When a prompt regresses, CI fails.

// community

Works beautifully with your stack.

Loved by developers

Developers and their agents, shipping with Pest.

View more on GitHub →
"Pest is minimal, distraction-free, and a joy to use."
Taylor Otwell
Taylor Otwell Creator of Laravel
"Pest’s DX is unmatched. It just feels right."
Caleb Porzio
Caleb Porzio Creator of Livewire
"Pest is the way."
Jeffrey Way
Jeffrey Way Laracasts Owner
70M+ Downloads
60+ Pest plugins
12k+ GitHub Stars
300+ Contributors

Bring back the joy of testing. Again.

The biggest release of Pest yet — for most suites, a one-line upgrade.