/pest-arch-test-snippets

Useful code snippets for Architecture test for PEST

PEST 'Architecture test' code snippets

Useful 'Architecture test' code snippets for PEST which you can use in your Laravel projects.

PR and ideas are welcome! 🙌

Table of contents


Do not leave debug statements

It's easy to leave debug statements like dd or dump in the code and push them to production.

But now we can avoid that by adding the following test.

arch('Do not leave debug statements')
    ->expect(['dd', 'dump', 'var_dump'])
    ->not->toBeUsed();

If you are using Ray you should add ray to the expectation list as well.

Do not use env() outside of config files

If we use config:cache in production (which we should), env() helper will always return null.
But it's very easy to forget while writing code!

Add the following test to make sure we are not doing that.

arch('Do not use env helper in code')
    ->expect(['env'])
    ->not->toBeUsed();

Use strict type checking

We might prefer to use Strict type checking in our code.

To ensure that, we can add the following test:

arch('Use string type check')
    ->expect('App')
    ->toUseStrictTypes();

Invokable classes should have __invoke method

Sometimes we want to make sure that some classes should be invokable. For example, some developers prefer that Action classes should be invokable.

To ensure that, we can add the following test:

arch('Action classes should be invokable')
    ->expect('App\Actions')
    ->toBeInvokable();

Classes should contain a specific method

A lot of Laravel developers prefer to useLaravel actions. This classes must have a handle method. Also, [Laravel Jobs] should have a handle method as well.

Using the following test, we can make sure that these classes must have the handle method implemented:

arch('Job classes should have handle method')
    ->expect('App\Jobs')
    ->toHaveMethod('handle');

Classes should implement an interface

When implementing the Repository pattern, it's a common practice to have a RepositoryInterface and all the Repository classes implement it.

How to make sure no Repository classes missed this requirement? It's pretty easy:

arch('app')
    ->expect('App\Repositories')
    ->toImplement('App\Repositories\RepositoryInterface');

Classes should have proper suffix

Service pattern is also a popular choice by the Laravel developers. In this case, we might want to make sure that all the 'Service' classes have the 'Service' suffix in it.

To confirm this, we can add this test:

arch('Services classes should have proper suffix')
    ->expect('App\Services')
    ->toHaveSuffix('Service');

We do the same for 'Controller' classes, right?

arch('Controller classes should have proper suffix')
    ->expect('App\Controllers')
    ->toHaveSuffix('Controller');

Ensure cross-domain boundaries are respected

When implementing 'Domains' or 'Modules' in our code, we might want to make sure that one domains/modules code is not directly used in other domains/modules. This will help us to keep the domains/modules independent of each other.

For example, let's say we have two Modules in our project called RideSharing and FoodDelivery. We want to make sure that one modules code is not used in other module. To ensure this constraint, we can just add this:

arch('Modules should be independent')
    ->expect('Modules\RideSharing')
    ->not->toBeUsed('Modules\FoodDelivery');

Do not access session data in Async jobs

In asynchronous jobs, session data is not available. Because we process asynchronous jobs with Queue workers later. This is why it's a good practice to avoid using helpers like, session, request, auth etc. in our asynchronous jobs.

To ensure this constraint, we can just add this:

arch('Do not access session data in Async jobs')
    ->expect([
        'session',
        'auth',
        'request',
        'Illuminate\Support\Facades\Auth',
        'Illuminate\Support\Facades\Session',
        'Illuminate\Http\Request',
        'Illuminate\Support\Facades\Request'
    ])
    ->each->not->toBeUsedIn('App\Jobs');