spatie/pest-plugin-route-testing
Pest plugin for Laravel that automatically tests all your app’s GET routes. Run a single test to assert responses are successful, redirects, forbidden, not found, etc. Filter routes by pattern and provide models for route model bindings via bind().
Installation:
composer require --dev spatie/pest-plugin-route-testing
Ensure spatie/pest-plugin is also installed (this package is a plugin for Pest).
First Test File:
Create a test file (e.g., tests/Feature/RouteTests.php) and add:
use function Spatie\RouteTesting\routeTesting;
it('ensures all GET routes return success', function () {
routeTesting('all GET routes')
->assertSuccessful();
});
Run with:
./vendor/bin/pest
First Use Case:
Verify all public-facing routes (e.g., /, /about, /contact) return 200. Useful for:
Testing All Routes:
routeTesting('all routes')
->assertSuccessful();
->get() or ->post() to filter HTTP methods.Scoped Testing:
routeTesting('admin routes')
->include('admin/*')
->assertSuccessful();
include(): Whitelist routes (supports glob patterns like admin/* or regex).exclude(): Blacklist routes (e.g., ->exclude('api/*')).HTTP Method Filtering:
routeTesting('API endpoints')
->post()
->put()
->assertSuccessful();
get(), post(), etc.) to test specific verbs.Route Model Bindings:
routeTesting('user profile routes')
->include('users/*')
->bind(User::factory()) // Auto-generates a fake user
->assertSuccessful();
bind(): Provides fake models for routes like /users/{user}.Custom Assertions:
routeTesting('auth routes')
->include('login', 'register')
->assertRedirect();
TestResponse assertions (e.g., assertForbidden(), assertSee()).Combine with Pest Plugins:
use function Pest\Laravel\actingAs;
use function Spatie\RouteTesting\routeTesting;
it('tests authenticated routes', function () {
actingAs(User::factory()->create());
routeTesting('authenticated routes')
->include('dashboard/*')
->assertSuccessful();
});
Dynamic Route Testing:
it('tests routes in a feature branch', function () {
$routes = Route::getRoutes()->getRoutes();
$newRoutes = collect($routes)->filter(fn ($route) =>
str_contains($route->uri(), 'new-feature')
);
routeTesting('new feature routes')
->routes($newRoutes)
->assertSuccessful();
});
CI/CD Hooks:
Add to .github/workflows/test.yml:
- name: Test Routes
run: ./vendor/bin/pest --filter "routeTesting"
Local Development:
Use in php artisan tinker to debug:
\Spatie\RouteTesting\routeTesting('broken routes')
->exclude('health-check')
->dd(); // Dumps failing routes
Route Model Bindings:
/users/{user} fail if no model is bound.->bind(User::factory()) or exclude them with ->exclude('users/*').Middleware Conflicts:
auth middleware may fail if unauthenticated.actingAs() (Pest/Laravel plugin).Dynamic Routes:
/posts/{id?}) may not match expectations.->include('posts/*').Performance:
->include('api/*')) or run in parallel with Pest’s --parallel flag.Environment-Specific Routes:
/admin may not exist in testing env.->onlyIn('local') (if supported) or mock routes in routes/web.php for testing.Inspect Failing Routes:
routeTesting('debug routes')
->dd(); // Dumps all routes with metadata (URI, methods, middleware)
Log Route Failures:
routeTesting('log failures')
->assertSuccessful()
->fail(function (array $failedRoutes) {
foreach ($failedRoutes as $route) {
Log::error("Failed route: {$route['uri']} (HTTP: {$route['response']->status()})");
}
});
Skip Routes Temporarily:
routeTesting('skip maintenance routes')
->exclude('maintenance')
->assertSuccessful();
Custom Assertions:
Extend Spatie\RouteTesting\RouteTester to add assertions:
namespace App\Tests\Extensions;
use Spatie\RouteTesting\RouteTester;
class CustomAssertions extends RouteTester
{
public function assertHasJsonApiError(): static
{
return $this->assertJsonStructure(['errors']);
}
}
Use in tests:
routeTesting('API errors')
->post()
->assertHasJsonApiError();
Predefined Route Groups: Create a helper trait:
trait RouteGroups
{
protected function adminRoutes(): array
{
return ['admin/*'];
}
}
Use in tests:
routeTesting('admin panel')
->include($this->adminRoutes())
->assertSuccessful();
Hook into Pest Events:
beforeEach(function () {
if (app()->environment('testing')) {
\Spatie\RouteTesting\routeTesting('pre-flight check')
->exclude('health-check')
->assertSuccessful();
}
});
How can I help you explore Laravel packages today?