Structure of Tests

A consistent pattern for every test class

Things are predictable and easy to scan.

// tests/Feature/Http/Controllers/UserController/CeateTest.php

// 1. App\Http\Controllers\UserController -> namespace matches
namespace Tests\Feature\Http\Controllers\UserController;

// 2. which class is tested
#[CoversClass(UserController::class)]

// 3. which method is tested
#[CoversMethod(UserController::class, 'Create')]
class CreateTest extends TestCase
{
    // 4. param that can be used throughout
    public User $user;

    protected function setUp(): void
    {
        parent::setUp();

        // 5. creating local param
        $this->user = User::factory()->create();

        // 6. assign all fakes here
        Queue::fake();
        Mail::fake();
    }

    #[Test]
    public function foo(): void
    {
        //...
    }

    #[Test]
    public function bar(): void
    {
        // 7. update user if needed in the arrange phase
        $this->user->update(['active' => false]);
        //...
    }
}

Seven steps. Same order. Every time.