Pest: RFC: Namespacing functions

Created on 31 May 2020  ·  4Comments  ·  Source: pestphp/pest

In the current state of Pest, we could say that PHPUnit static functions like assertions are being injected in the global namespace, and functions specific to the test case are being served thought the $this variable. Here is an example:

<?php

beforeEach(fn () => $this->withoutMiddleware()); // `$this` being used

test('example test', function () {
    assertTrue(true); // `assertTrue` function being used
});

it('has welcome page', function () {
    $this->get('/')->assertSee('Laravel'); // `$this` being used
});

The current approach has a few problems: there is no autocompletion on the $this, and for some developers gets complicated to understand what is available globally and what's available on the $this.

Proposal: Serve namespaced functions for assertions/methods specific to the test case.

✓ No more autocompletion issues
✓ Makes things a little bit more consistent as everything gets available using just simple functions

PHPUnit static functions like assertTrue or assertArrayHas will be still available globally, but assertions/methods specific to the test case would require a use statement. Here is how it could look like:

<?php

use function Pest\Laravel\{get, withoutMiddleware};

beforeEach(fn () => withoutMiddleware());

test('example test', function () {
    assertTrue(true);
});

it('has welcome page', function () {
    get('/')->assertSee('Laravel');
});

The $this is still available for people that want to copy/paste the current PHPUnit test. So no breaking changes are being proposed here.

I am still not sure about this, as it requires one or more extra lines per test. So let me know.

enhancement help wanted

Most helpful comment

I think this a good idea. 👍 It would solve the issue for people who dislike the global functions, and also resolve any issues for functions that may be provided by 2 different plugins.

All 4 comments

Won't something like that solve the autocompletion issue?

/** @var $this TestCase */

I think this a good idea. 👍 It would solve the issue for people who dislike the global functions, and also resolve any issues for functions that may be provided by 2 different plugins.

The consistency and ease of use gains trumps the visual burden of the additional line, I would go for it 👍

Plus, real-world tests will also have use statements, and in the end one more line isn't adding too much distraction:

<?php

use App\User;
use Livewire\Livewire;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use function Pest\Laravel\{get, withoutMiddleware};

test('can view login page', function () {
    get(route('login'))
        ->assertSuccessful()
        ->assertSeeLivewire('auth.login');
})->group('auth');

test('is redirected if already logged in', function () {
    $user = factory(User::class)->create();

    actingAs($user)
        ->get(route('login'))
        ->assertRedirect(route('home'));
})->group('auth');

[…]

VS

<?php


use App\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Livewire\Livewire;
use Livewire\Livewire;

test('can view login page', function () {
    $this->get(route('login'))
         ->assertSuccessful()
         ->assertSeeLivewire('auth.login');
})->group('auth');

test('is redirected if already logged in', function () {
    $user = factory(User::class)->create();

    $this->actingAs($user);

    $this->get(route('login'))
         ->assertRedirect(route('home'));
})->group('auth');

[…]

To me the first example is easier to read, because everything of importance is aligned on a vertical ligne. This allows quick scanning of the important code (this is an information design good practice).

In progress for PHP 0.2.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nunomaduro picture nunomaduro  ·  7Comments

reed-jones picture reed-jones  ·  6Comments

rihardssceredins picture rihardssceredins  ·  5Comments

albertpratomo picture albertpratomo  ·  7Comments

Synchro picture Synchro  ·  5Comments