Quality
laravel-testing
Generates Pest PHP tests - unit, feature, API, browser
Overview
The laravel-testing agent generates comprehensive test suites using Pest PHP. It analyzes your code and creates tests covering happy paths, edge cases, validation, authorization, and database interactions.
Test Types Generated
| Type | Location | Use Case |
|---|---|---|
| Unit Tests | tests/Unit/ |
Isolated class testing, services, helpers |
| Feature Tests | tests/Feature/ |
HTTP endpoints, middleware, full request cycle |
| API Tests | tests/Feature/Api/ |
JSON API assertions, authentication flows |
| Livewire Tests | tests/Feature/Livewire/ |
Component interactions, wire:model, events |
| Browser Tests | tests/Browser/ |
Laravel Dusk end-to-end testing |
Pest PHP Features Used
Generated tests leverage modern Pest PHP syntax:
<?php
use App\Models\User;
use App\Models\Order;
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
describe('Order Management', function () {
beforeEach(function () {
$this->user = User::factory()->create();
});
describe('creating orders', function () {
it('creates an order with valid data', function () {
$response = $this->actingAs($this->user)
->postJson('/api/orders', [
'product_id' => 1,
'quantity' => 2,
]);
$response->assertCreated();
expect(Order::count())->toBe(1);
});
it('validates required fields', function () {
$response = $this->actingAs($this->user)
->postJson('/api/orders', []);
$response->assertUnprocessable()
->assertJsonValidationErrors(['product_id', 'quantity']);
});
});
describe('authorization', function () {
it('prevents guests from creating orders', function () {
$response = $this->postJson('/api/orders', [
'product_id' => 1,
]);
$response->assertUnauthorized();
});
it('prevents users from viewing others orders', function () {
$otherUser = User::factory()->create();
$order = Order::factory()->for($otherUser)->create();
$response = $this->actingAs($this->user)
->getJson("/api/orders/{$order->id}");
$response->assertForbidden();
});
});
});
Test Coverage Areas
The agent automatically generates tests for:
- Happy paths - Standard successful operations
- Validation - Required fields, formats, uniqueness
- Authorization - Policies, gates, role checks
- Database state - assertDatabaseHas/Missing
- Edge cases - Null values, boundaries, empty inputs
- Relationships - Cascade deletes, constraints
Factory Integration
Tests use model factories for realistic data:
// Generated factory usage
it('lists orders with pagination', function () {
Order::factory()
->count(25)
->for($this->user)
->create();
$response = $this->actingAs($this->user)
->getJson('/api/orders');
$response->assertOk()
->assertJsonCount(15, 'data')
->assertJsonPath('meta.total', 25);
});
// With specific states
it('shows only pending orders', function () {
Order::factory()->pending()->count(3)->for($this->user)->create();
Order::factory()->completed()->count(2)->for($this->user)->create();
$response = $this->actingAs($this->user)
->getJson('/api/orders?status=pending');
$response->assertJsonCount(3, 'data');
});
Mocking External Services
The agent generates mocks for external dependencies:
use App\Services\PaymentGateway;
it('processes payment successfully', function () {
$mock = Mockery::mock(PaymentGateway::class);
$mock->shouldReceive('charge')
->once()
->with(100.00, Mockery::any())
->andReturn(['status' => 'success', 'transaction_id' => 'txn_123']);
$this->app->instance(PaymentGateway::class, $mock);
$response = $this->actingAs($this->user)
->postJson('/api/checkout', ['amount' => 100.00]);
$response->assertOk()
->assertJsonPath('transaction_id', 'txn_123');
});
Invoked By Commands
- /laravel-agent:test:make - Generate tests for a class/feature
- /laravel-agent:test:coverage - Run tests with coverage report
Best Practices
- One concept per test - Test one behavior at a time
- Descriptive names - it('creates order with valid data')
- Arrange-Act-Assert - Clear test structure
- Factories for data - Never hardcode test data
- Mock external services - Don't hit real APIs in tests
Guardrails
The testing agent follows strict rules:
- ALWAYS use RefreshDatabase trait for database tests
- ALWAYS mock external services (payment gateways, APIs)
- ALWAYS test authorization (403 responses)
- NEVER share state between tests
- NEVER test private methods directly
See Also
- laravel-feature-builder - Creates features with tests included
- laravel-testing skill - Auto-invoked testing expertise