How to test all routes in your Laravel app by writing just a single Pest test
We’ve released a new package called spatie/pest-plugin-route-testing. This package can test all common routes in your Laravel app by writing a single test.
In this blog post, I’d like to tell you all about it.
Why this package was created
When people start out writing tests for their Laravel apps, I usually give the advice to test your home page. The homepage usually is a very simple URL to test; it’s just a simple GET request. Here’s a video that explains how to test the homepage taken from our Testing Laravel course. Here’s how such a test could like:
it('can render the homepage', function() { $this ->get('/') ->assertSuccessful(); });
Now, in real-world applications, there are typically more simple pages like the homepage, where you could write a simple test to make sure that it works. When adding simple pages to your application, it’s easy to forget to write a test for them.
That’s why we created our new spatie/pest-plugin-route-testing package. It allows you to write a single test to make sure all simple GET requests like pages in your app work.
Using spatie/pest-plugin-route-testing
use function Spatie\RouteTesting\routeTesting; routeTesting('all GET routes')->assertSuccessful();
This will test all GET routes in your application and ensure they return a 200 HTTP status code. Here's what the output looks like when you run this test in a small app.
Instead of assertSuccessful()
, you can use any assertion that is available in Laravel's TestResponse
class, such as assertRedirect()
, assertNotFound()
, assertForbidden()
, etc.
You can also test specific routes:
use function Spatie\RouteTesting\routeTesting; routeTesting('all blog routes') ->include('blog*') ->assertSuccessful();
If there are routes that have route model bindings, the package will skip the test for those routes. Let's assume you have a route defined as user/{user}
. Here's what the output looks like when you run the test.
If you want to test a route with a route model binding, you can provide the model using the bind
method.
use function Spatie\RouteTesting\routeTesting; use App\Models\User; routeTesting('all blog routes') ->bind('user', User::factory()->create()) ->assertSuccessful();
When you run the test now, the package will use the provided model to test the route.
If you want to exclude routes from the test, you can use the exclude
method. Here's an example that tests all routes except the ones that start with admin
.
use function Spatie\RouteTesting\routeTesting; routeTesting('all blog routes') ->exclude('admin*') ->assertSuccessful();
You can use the setUp
method to execute code before the route test is run. Here's an example where we log in a user before running the test.
use function Spatie\RouteTesting\routeTesting; routeTesting('all admin routes') ->setUp(function () { $user = User::factory()->create(); $this->actingAs($user); // optionally, you could also bind the model $this->bind('user', $user); }) ->include('admin*') ->assertSuccessful();
In closing
Using spatie/pest-plugin-route-testing, it’s easy to test all simple pages of your Laravel app. New pages will automatically be tested too.
My colleague Niels came up with the original idea for this package, and Alex did a big refactor on the internals.
This isn’t the first package our team has created. You can see everything we do in open-source on the open-source pages on our company website.