About laravel-testing
laravel-testing is a testing skill for Laravel developers, covering feature, unit, and architecture tests with Pest and PHPUnit. It also provides guidance for HTTP, database, mocking, and Artisan command tests.
Key features
- 01Feature, unit, and architecture tests
- 02Pest syntax and datasets
- 03HTTP and JSON assertions
- 04Database, factories, and assertions
- 05Service, event, and HTTP mocking
- 06Artisan command tests
Use cases
- 01Validate HTTP endpoints and full-stack flows
- 02Test service or policy logic
- 03Check code architecture rules
- 04Fake external APIs, mail, queues, and events
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ fusengine/ agents --skill laravel-testingAfter installing, type/laravel-testingin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/console-tests.mddatabase-assertions.mddatabase-basics.mddatabase-factories.mdhttp-assertions.mdhttp-auth.mdhttp-json.mdhttp-requests.mdmocking-fakes.mdmocking-http.mdmocking-services.mdpest-arch.mdpest-basics.mdpest-datasets.mdtroubleshooting.mdreferences/templates/ApiTest.php.mdArchTest.php.mdFeatureTest.php.mdPestConfig.php.mdUnitTest.php.mdDetails
From the project READMELaravel Testing
Agent Workflow (MANDATORY)
Before ANY implementation, spawn 3 agents in parallel, one Agent call each with a name:
- fuse-ai-pilot:explore-codebase - Analyze existing test patterns
- fuse-ai-pilot:research-expert - Verify Pest/PHPUnit docs via Context7
- mcp__context7__query-docs - Check assertion and mocking patterns
After implementation, run fuse-ai-pilot:sniper for validation.
Overview
| Type | Purpose | Location |
|---|---|---|
| Feature | HTTP, full stack | tests/Feature/ |
| Unit | Isolated classes | tests/Unit/ |
| Arch | Code architecture | tests/Arch.php |
Decision Guide: Test Type
What to test?
├── HTTP endpoint → Feature test
├── Service/Policy logic → Unit test
├── Code structure → Arch test
├── External API → Mock with Http::fake()
├── Mail/Queue/Event → Use Fakes
└── Database state → assertDatabaseHas()
Decision Guide: Test Strategy
Coverage strategy?
├── Feature tests (70%) → Critical flows
├── Unit tests (25%) → Business logic
├── E2E tests (5%) → User journeys
└── Arch tests → Structural rules
Critical Rules
- Use RefreshDatabase for database isolation
- Use factories for test data (never raw inserts)
- Mock external services - Never call real APIs
- Test edge cases - Empty, null, boundaries
- Run parallel -
pest --parallelfor speed
Reference Guide
Pest Basics
| Topic | Reference | When to Consult |
|---|---|---|
| Pest Syntax | pest-basics.md | it(), test(), describe() |
| Datasets | pest-datasets.md | Data providers, hooks |
| Architecture | pest-arch.md | arch() tests |
HTTP Testing
| Topic | Reference | When to Consult |
|---|---|---|
| Requests | http-requests.md | GET, POST, headers |
| JSON API | http-json.md | API assertions |
| Authentication | http-auth.md | actingAs, guards |
| Assertions | http-assertions.md | Status, redirects |
Database Testing
| Topic | Reference | When to Consult |
|---|---|---|
| Basics | database-basics.md | RefreshDatabase |
| Factories | database-factories.md | Factory patterns |
| Assertions | database-assertions.md | DB assertions |
Mocking
| Topic | Reference | When to Consult |
|---|---|---|
| Services | mocking-services.md | Mock, spy |
| Fakes | mocking-fakes.md | Mail, Queue, Event |
| HTTP & Time | mocking-http.md | Http::fake, travel |
Other
| Topic | Reference | When to Consult |
|---|---|---|
| Console | console-tests.md | Artisan tests |
| Troubleshooting | troubleshooting.md | Common errors |
Templates
| Template | When to Use |
|---|---|
| FeatureTest.php.md | HTTP feature test |
| UnitTest.php.md | Service unit test |
| ArchTest.php.md | Architecture test |
| ApiTest.php.md | REST API test |
| PestConfig.php.md | Pest configuration |
Quick Reference
// Feature test
it('creates a post', function () {
$user = User::factory()->create();
$this->actingAs($user)
->postJson('/api/posts', ['title' => 'Test'])
->assertCreated()
->assertJsonPath('data.title', 'Test');
$this->assertDatabaseHas('posts', ['title' => 'Test']);
});
// With dataset
it('validates emails', function (string $email, bool $valid) {
// test logic
})->with([
['[email protected]', true],
['invalid', false],
]);
// Mock facade
Mail::fake();
// ... action ...
Mail::assertSent(OrderShipped::class);
Commands
# Run all tests
php artisan test
# Pest directly
./vendor/bin/pest
# Parallel execution
./vendor/bin/pest --parallel
# Filter by name
./vendor/bin/pest --filter "user can"
# Coverage
./vendor/bin/pest --coverage --min=80
# Profile slow tests
./vendor/bin/pest --profile
Best Practices
DO
- Use
RefreshDatabasetrait - Follow AAA pattern (Arrange-Act-Assert)
- Name tests descriptively
- Test one thing per test
- Use factories for data
DON'T
- Create test dependencies
- Call real external APIs
- Use production database
- Skip edge cases
Laravel 13 Notes
PHPUnit 12/13 + Pest 4/5
The Laravel 13 skeleton ships PHPUnit 12 (^12.5); the framework also accepts PHPUnit 13. Pest 5 (current, requires PHP 8.4+ and PHPUnit 13, plus pestphp/pest-plugin-laravel ^5.0 which needs Laravel ^13.23) — stay on Pest 4 (PHPUnit 12) if the app still runs PHP 8.3. PHP attributes replace docblock annotations.
use PHPUnit\Framework\Attributes\Test;
use Illuminate\Foundation\Testing\Attributes\Seed;
use Illuminate\Foundation\Testing\Attributes\Seeder;
#[Seed] // runs DatabaseSeeder
#[Seeder(UserSeeder::class)] // runs a targeted seeder
final class UserTest extends TestCase
{
#[Test]
public function it_creates_user(): void { /* ... */ }
}
Str factories reset
Laravel 13 resets custom Str factories (UUID / ULID / random string) during test teardown. Tests relying on a factory persisting across methods must set it in each test or setup hook.
#[UnitTest] (L13)
Illuminate\Foundation\Testing\Attributes\UnitTest on a test method skips booting the application for that test.
Migration from Pest 3 → 4
- Bump
pestphp/pestand all Pest plugins to^4.0(PHP 8.3+, PHPUnit 12) - Snapshot names changed: run
./vendor/bin/pest --update-snapshots pest-plugin-watchandpest-plugin-fakerare archived
Migration from Pest 4 → 5
- Requires PHP 8.4+; bump
pestphp/pestand all Pest plugins to^5.0(built on PHPUnit 13) - New in 5:
--tia(test impact analysis, local only), first-party PHPStan/Rector plugins, Agent and Evals plugins, time-balanced sharding