Weave Code
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

Pest Laravel Package

pestphp/pest

Pest is an elegant PHP testing framework focused on simplicity and a joyful developer experience. Write expressive tests with a clean syntax, run fast suites, and scale from tiny projects to large apps. Full docs at pestphp.com.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require pestphp/pest --dev --with-all-dependencies
    

    For Laravel projects, Pest is pre-installed in Laravel 10+.

  2. First Test: Replace tests/Feature/ExampleTest.php with:

    use Pest\Test;
    
    test('the application returns a successful response', function () {
        $response = $this->get('/');
    
        $response->assertOk();
    });
    
  3. Run Tests:

    ./vendor/bin/pest
    

Where to Look First

First Use Case

Test a Laravel API Endpoint:

test('create a new user', function () {
    $response = $this->post('/api/register', [
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'password' => 'password',
    ]);

    $response->assertCreated()
             ->assertJsonStructure(['data' => ['id', 'name', 'email']]);
});

Implementation Patterns

Core Workflows

  1. Test Organization: Use describe() for grouping related tests:

    describe('User Authentication', function () {
        it('fails with invalid credentials', function () {
            $this->post('/login', ['email' => 'wrong@example.com', 'password' => 'wrong'])
                 ->assertUnauthorized();
        });
    });
    
  2. Data-Driven Testing: Leverage with() for datasets:

    test('validate user input', function (string $email, string $password) {
        $this->post('/register', compact('email', 'password'))
             ->assertValidationErrors([$email ? 'email' : 'required', 'password']);
    })->with([
        ['test@example.com', 'password'],
        ['', 'password'],
        ['test@example.com', ''],
    ]);
    
  3. Mocking & Stubbing: Use Pest’s fluent syntax:

    test('fetch user data from external API', function () {
        $this->mock(\Illuminate\Http\Client\PendingRequest::class)
             ->shouldReceive('get')
             ->once()
             ->andReturn(['id' => 1, 'name' => 'John']);
    
        $user = $this->get('/api/user/1')->json();
        expect($user)->toBe(['id' => 1, 'name' => 'John']);
    });
    
  4. Browser Testing: Playwright-powered E2E tests:

    test('user can login via browser', function () {
        $this->browse()
             ->visit('/login')
             ->type('email', 'test@example.com')
             ->type('password', 'password')
             ->press('Login')
             ->assertPathIs('/dashboard');
    });
    

Integration Tips

  • Laravel Artisan Commands: Test commands with $this->artisan():

    test('run migrate command', function () {
        $this->artisan('migrate:fresh')
             ->expectsOutput('Migrations run successfully.')
             ->assertExitCode(0);
    });
    
  • Jobs & Queues: Use $this->queue() helper:

    test('dispatch and assert job', function () {
        $this->queue(function () {
            SendEmailJob::dispatch('test@example.com');
        });
    
        $this->assertQueued(SendEmailJob::class);
    });
    
  • Database Transactions: Pest auto-rolls back transactions. For custom logic:

    test('test with fresh database', function () {
        $this->freshDatabase();
        // Test logic here
    });
    
  • Parallel Testing: Run tests in parallel for faster CI:

    ./vendor/bin/pest --parallel
    

Advanced Patterns

  1. Test Isolation: Use beforeEach() and afterEach():

    beforeEach(function () {
        $this->actingAs(User::factory()->create());
    });
    
    afterEach(function () {
        Cache::flush();
    });
    
  2. Snapshots Testing: Compare outputs against snapshots:

    test('API response matches snapshot', function () {
        $response = $this->get('/api/data');
        expect($response->json())->toMatchSnapshot();
    });
    
  3. Architecture Testing: Enforce coding standards:

    test('App\\Http\\Controllers should not use global functions', function () {
        expect('App\Http\Controllers')
            ->not->toUseGlobalFunctions();
    });
    
  4. Flaky Test Handling: Mark flaky tests:

    flaky('login sometimes fails due to race condition', function () {
        $this->post('/login', [...])->assertOk();
    });
    

Gotchas and Tips

Pitfalls

  1. Preset Conflicts:

    • Issue: Laravel presets may not include all expected helpers (e.g., Rules).
    • Fix: Manually import missing presets:
      use Pest\Laravel\Rules;
      
  2. Parallel Testing Quirks:

    • Issue: Shared state (e.g., static variables) can cause race conditions.
    • Fix: Avoid static state or use --shard with time-based balancing:
      ./vendor/bin/pest --update-shards  # Generate shard data
      ./vendor/bin/pest --shard=1/4      # Run shard 1 of 4
      
  3. Browser Test Isolation:

    • Issue: Browser tests share context by default.
    • Fix: Use ->newBrowser() for isolated sessions:
      test('parallel browser tests', function () {
          $this->browse()->newBrowser()->visit('/');
      });
      
  4. Snapshot Mismatches:

    • Issue: Snapshots fail due to minor changes (e.g., timestamps).
    • Fix: Use --update-snapshots to regenerate:
      ./vendor/bin/pest --update-snapshots
      
  5. CI-Specific Issues:

    • Issue: --teamcity flag may not work with Paratest.
    • Fix: Use --teamcity with --parallel explicitly:
      ./vendor/bin/pest --parallel --teamcity
      

Debugging Tips

  1. Verbose Output: Run tests with -v for details:

    ./vendor/bin/pest -v
    
  2. Test Filtering: Run specific tests:

    ./vendor/bin/pest Tests/Feature/AuthTest.php::test_login
    
  3. Xdebug Integration: Use --debug for Xdebug:

    ./vendor/bin/pest --debug
    
  4. Coverage Exclusions: Exclude directories from coverage:

    ./vendor/bin/pest --coverage --exclude=tests/Feature/Browser/
    

Configuration Quirks

  1. Custom Test Directory: Configure in pest.php:

    return [
        'stubs' => [
            'test_case' => __DIR__.'/stubs/TestCase.php',
        ],
    ];
    
  2. PHPUnit Integration: Pest uses PHPUnit under the hood. Override PHPUnit config in phpunit.xml:

    <php>
        <env name="APP_ENV" value="testing"/>
    </php>
    
  3. Browser Test Headless Mode: Disable headful mode in pest.php:

    return [
        'browser' => [
            'headful' => false,
        ],
    ];
    

Extension Points

  1. Custom Assertions: Extend Pest’s assertions in tests/CreatesApplication.php:

    use Pest\Expectation;
    
    Expectation::extend('toBeEven', function (int $value) {
        return $value % 2 === 0;
    });
    
  2. Preset Extensions: Add custom presets:

    use Pest\Laravel\Laravel;
    
    Laravel::macro('toBeAdmin', function () {
        return $this->actingAs(User::factory()->admin()->create());
    });
    
  3. Plugin Development: Create custom plugins (e.g., for API testing):

    // tests/Plugins/ApiTestPlugin.php
    namespace Tests\Plugins;
    
    use Pest\Plugin;
    
    class ApiTestPlugin implements Plugin
    {
        public function register(): void
        {
            // Register custom test methods
        }
    }
    
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai