Quickly Generating Tests Files For Your Laravel Application

Last updated 06/11/2021

Keep your test directory in sync with your application structure and keep your test suite organised

One of the biggest challenges when writing tests is maintaining a readable suite over time. When I first started writing tests, I would place everything in the root of the tests directory. As you can imagine, once your test suite begins to grow, this can quickly get messy.

I've tried a lot of different methods for organising tests over the years, but the more tests I write, the more I realise that I want my test suite structure to match the structure of my application. For example, if I have a UserController in the app/Http/Controllers/Admin/UserController.php file, I want a feature test at tests/Feature/Http/Controllers/Admin/UserControllerTest.php.

The issue is that it's super annoying to have to keep these folders in sync. Typing out these long namespaces twice (once for the controller and once for the test) each time I create a new class is super frustrating. In code, anything that is super frustrating usually needs a better implementation.

So, as of Laravel 8.65, you can now add the --pest or --test option to various php artisan make commands. When you do, you'll get a matching test for that generated class. Here's an example:

Using the new pest option

In this example, two files have been generated:

  1. app/Http/Controllers/Admin/UserController.php
  2. tests/Feature/Http/Controllers/Admin/UserControllerTest.php

Nice, hey? It's less work for the developer, which makes it more likely that we'll actually create the tests in the first place. Afterall, it's now just 4 letters away. Here are the Artisan commands you can use it on currently:

  • php artisan make:command
  • php artisan make:job
  • php artisan make:listener
  • php artisan make:mail
  • php artisan make:model
  • php artisan make:notification
  • php artisan make:controller
  • php artisan make:middleware

Adding matching tests for your own artisan commands

If you're a Laravel package developer, or even if you have a large Laravel application, you may have a few of your own custom make Artisan commands. You'll be happy to know that it's insanely simple to add this functionality to those commands. There are two requirements: your command extends the Illuminate\Console\GeneratorCommand class and you use the Illuminate\Console\Concerns\CreatesMatchingTest. Here's an example:

1<?php
2 
3namespace Illuminate\Foundation\Console;
4 
5use Illuminate\Console\Concerns\CreatesMatchingTest;
6use Illuminate\Console\GeneratorCommand;
7 
8class MyCustomMakeCommand extends GeneratorCommand
9{
10 use CreatesMatchingTest;

That's it! Simply by adding the new CreatesMatchingTest trait, your custom Artisan command now has a --pest and --test option that will allow other developers to easily add matching tests when using your command.

Wrapping up

I'm a big believer in convention over customisation. Sticking to a single paradigm is essential for a maintainable test suite, and the new --pest and --test options help enable that with no extra effort.

I hope you like this addition to the framework as much as I do. Keep writing those tests!

Regards, Luke