logo
podcast Podcast
get help Get Unstuck

Write command tests in a consistent way

Have one way of doing things

Joel Clermont
Joel Clermont
2024-07-19

Laravel often gives us more than one way to do something. This is great for flexibility, but I like having one typical approach that's used throughout an application.

To demonstrate this, let's look at some basic ways we can test a command in Laravel.

There are two different ways to call the command, and then two different ways to specify the command:

// these are all equivalent
Artisan::call('my:command');
$this->artisan('my:command');

Artisan::call(MyCommand::class);
$this->artisan(MyCommand::class);

Four different ways of doing the same thing, and I've seen them used interchangeably in the same codebase.

My preference is the last option. Use the artisan helper on the base test class, and specify the command by using the class name.

Why? The artisan helper is designed for testing commands, so you can fluently chain assertions to the call. Also, by specifying the class name instead of the command as a string, refactoring and code navigation becomes a lot easier.

Next up: assertions. You could assertExitCode and specify a number, but I prefer to use the assertSuccessful and assertFailed methods.

Why? I rarely (maybe never?) use exit codes other than 0 or 1, so the more readable method names make it easier to scan and understand the test.

If you find you're using a mix of approaches, I recommend picking one and refactoring your tests. It's a simple mechanical change that leads to more consistent and readable tests.

Here to help,

Joel

P.S. Ash Allen's book "Battle Ready Laravel" includes a whole section on testing. If you're looking for a way to start, I recommend checking it out.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.