Byproduct of the Laravel 13 upgrade: composer's post-update-cmd runs `artisan boost:update`, and Boost went 2.1.3 to 2.4.x with the update. Refreshes CLAUDE.md and boost.json for the Laravel 13 / Livewire 4 stack, updates the livewire, pest and tailwindcss skills, replaces the developing-with-fortify skill with fortify-development, and adds new laravel-best-practices and octane-development skills. Generated output, not hand-edited. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.5 KiB
Markdown
44 lines
1.5 KiB
Markdown
# Testing Best Practices
|
|
|
|
## Use `LazilyRefreshDatabase` Over `RefreshDatabase`
|
|
|
|
`RefreshDatabase` migrates once per process and wraps each test in a rolled-back transaction. `LazilyRefreshDatabase` skips even that first migration if the schema is already up to date.
|
|
|
|
## Use Model Assertions Over Raw Database Assertions
|
|
|
|
Incorrect: `$this->assertDatabaseHas('users', ['id' => $user->id]);`
|
|
|
|
Correct: `$this->assertModelExists($user);`
|
|
|
|
More expressive, type-safe, and fails with clearer messages.
|
|
|
|
## Use Factory States and Sequences
|
|
|
|
Named states make tests self-documenting. Sequences eliminate repetitive setup.
|
|
|
|
Incorrect: `User::factory()->create(['email_verified_at' => null]);`
|
|
|
|
Correct: `User::factory()->unverified()->create();`
|
|
|
|
## Use `Exceptions::fake()` to Assert Exception Reporting
|
|
|
|
Instead of `withoutExceptionHandling()`, use `Exceptions::fake()` to assert the correct exception was reported while the request completes normally.
|
|
|
|
## Call `Event::fake()` After Factory Setup
|
|
|
|
Model factories rely on model events (e.g., `creating` to generate UUIDs). Calling `Event::fake()` before factory calls silences those events, producing broken models.
|
|
|
|
Incorrect: `Event::fake(); $user = User::factory()->create();`
|
|
|
|
Correct: `$user = User::factory()->create(); Event::fake();`
|
|
|
|
## Use `recycle()` to Share Relationship Instances Across Factories
|
|
|
|
Without `recycle()`, nested factories create separate instances of the same conceptual entity.
|
|
|
|
```php
|
|
Ticket::factory()
|
|
->recycle(Airline::factory()->create())
|
|
->create();
|
|
```
|