Skip to content

Feature Testing Laravel Applications with Pest

8 min read

Pest is the testing framework I wish existed when I started with Laravel. It's PHPUnit under the hood, but the expressive syntax makes tests a pleasure to read and write.

Why Pest Over PHPUnit Directly

Pest tests read like documentation:

// PHPUnit public function test_published_posts_are_visible(): void { $post = Post::factory()->published()->create(); $response = $this->get('/writing'); $response->assertStatus(200); $response->assertSee($post->title); } // Pest it('shows published posts on the writing page', function () { $post = Post::factory()->published()->create(); get('/writing') ->assertOk() ->assertSee($post->title); });

Test Structure I Use

tests/ Feature/ Site/ WritingTest.php -- public reading experience AiChatTest.php -- AI playground Admin/ PostsTest.php -- CRUD admin flows Unit/ SlugServiceTest.php

Database Strategy

I use RefreshDatabase for feature tests but LazilyRefreshDatabase in suites that don't modify the DB. For read-heavy tests, seeding once per suite saves significant time:

beforeAll(function () { Post::factory(20)->published()->create(); Post::factory(5)->draft()->create(); }); it('paginates at 10 posts', function () { get('/writing')->assertSee('Newer'); });

Testing Auth Flows

it('redirects guests away from admin', function () { get('/admin/posts')->assertRedirect('/login'); }); it('allows admins to create posts', function () { $admin = User::factory()->admin()->create(); actingAs($admin) ->post('/admin/posts', Post::factory()->make()->toArray()) ->assertRedirect(); expect(Post::count())->toBe(1); });

Datasets for Edge Cases

dataset('invalid slugs', [ 'empty string' => [''], 'only spaces' => [' '], 'too long' => [str_repeat('a', 256)], ]); it('rejects invalid slugs', function (string $slug) { actingAs(User::factory()->admin()->create()) ->post('/admin/posts', ['slug' => $slug]) ->assertInvalid('slug'); })->with('invalid slugs');
Share X / Twitter LinkedIn
A

Al Amin Ahamed

Senior software engineer & AI practitioner. Building things in Laravel, PHP, and TypeScript.

About me →

One email a month. No noise.

What I shipped, what I read, occasional deep dive. Unsubscribe anytime.