Laravel Testing Patterns: How I Write Every Test with Pest

I've written over 900 tests across Laravel Translations, Translations Pro, and kit. After that many tests, you develop strong opinions about what works. Here are the patterns I've settled on.

File Organization

Tests mirror the source directory structure:

Text

Feature tests go in tests/Feature/Http/Controllers/ grouped by domain, matching the action and controller structure. Unit tests go in tests/Unit/ mirroring the app/ structure. No exceptions.

Naming: Describe the Behavior

Test names should read like specifications:

PHP

If I read just the test names, I should understand what the application does.

The AAA Structure

Every test follows Arrange, Act, Assert. Always in that order. Always visually separated:

PHP

If a test has more than 3-4 lines of arrangement, the factory probably needs a new state.

Factory States Over Manual Setup

Instead of manually setting up model attributes in every test:

PHP

Define factory states:

PHP

Test the HTTP Layer, Not Internals

For feature tests, I test through the HTTP layer:

PHP

I'm testing the full request cycle: middleware, validation, authorization, controller logic, and database effect. If any layer breaks, this test catches it.

Always Test 403 and 422

Every endpoint gets at least three tests:

PHP

Happy path, authorization failure, validation failure. Every single endpoint.

Datasets for Validation Rules

When testing multiple validation rules on the same endpoint, datasets keep it clean:

PHP

What I Don't Test

  • Private methods (test them through public behavior)
  • Eloquent relationships (Laravel already tests those)
  • Framework features (middleware registration, config loading)
  • Getters and setters with no logic

If a test doesn't prevent a real bug, it's just maintenance overhead.

Running Tests

Always filter when developing:

Terminal

The --compact flag keeps the output clean. I can see at a glance what passed and what failed without scrolling through walls of green dots.

These patterns aren't revolutionary. They're boring, consistent, and reliable. That's exactly what a test suite should be.

Related articles