Database Testing

Introduzione

Laravel offre una varietà di strumenti utili e asserzioni per rendere più semplice testare le tue applicazioni basate sul database. Inoltre, le factory dei modelli Laravel e i seeders rendono facile creare record di database di test utilizzando i modelli Eloquent e le relazioni della tua applicazione. Discuteremo tutte queste potenti funzionalità nella documentazione seguente.

Resettare il Database Dopo Ogni Test

Prima di andare oltre, vediamo come resettare il database dopo ogni test in modo che i dati di un test precedente non interferiscano con quelli dei test successivi. Il trait Illuminate\Foundation\Testing\RefreshDatabase incluso in Laravel si occupa di questo per te. Basta usare il trait nella tua classe di test:

<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('basic example', function () {
    $response = $this->get('/');

    // ...
});
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Un esempio di test funzionale di base.
     */
    public function test_basic_example(): void
    {
        $response = $this->get('/');

        // ...
    }
}

Il trait Illuminate\Foundation\Testing\RefreshDatabase non esegue le migrazioni del database se lo schema è aggiornato. Invece, esegue il test all’interno di una transazione del database. Pertanto, eventuali record aggiunti al database da casi di test che non usano questo trait potrebbero ancora esistere nel database.

Se vuoi resettare completamente il database, puoi usare i trait Illuminate\Foundation\Testing\DatabaseMigrations o Illuminate\Foundation\Testing\DatabaseTruncation. Tuttavia, entrambe queste opzioni sono significativamente più lente rispetto al trait RefreshDatabase.

Model Factories

Durante i test, potrebbe essere necessario inserire alcuni record nel database prima di eseguire il test. Invece di specificare manualmente il valore di ogni colonna quando crei questi dati di test, Laravel permette di definire un insieme di attributi predefiniti per ciascuno dei tuoi Eloquent models usando le model factories.

Per saperne di più sulla creazione e l’utilizzo delle model factories per creare modelli, consulta la documentazione completa sulle model factory. Una volta definita una model factory, puoi utilizzare la factory nei tuoi test per creare modelli:

use App\Models\User;

test('models can be instantiated', function () {
    $user = User::factory()->create();

    // ...
});
use App\Models\User;

public function test_models_can_be_instantiated(): void
{
    $user = User::factory()->create();

    // ...
}

Esecuzione dei Seeders

Se desideri utilizzare i database seeders per popolare il tuo database durante un test funzionale, puoi invocare il metodo seed. Per impostazione predefinita, il metodo seed eseguirà il DatabaseSeeder, che dovrebbe eseguire tutti gli altri seeders. In alternativa, puoi passare il nome di una classe seeder specifica al metodo seed:

<?php

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('orders can be created', function () {
    // Esegui il DatabaseSeeder...
    $this->seed();

    // Esegui uno specifico seeder...
    $this->seed(OrderStatusSeeder::class);

    // ...

    // Esegui un array di seeders specifici...
    $this->seed([
        OrderStatusSeeder::class,
        TransactionStatusSeeder::class,
        // ...
    ]);
});
<?php

namespace Tests\Feature;

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Test per creare un nuovo ordine.
     */
    public function test_orders_can_be_created(): void
    {
        // Esegui il DatabaseSeeder...
        $this->seed();

        // Esegui uno specifico seeder...
        $this->seed(OrderStatusSeeder::class);

        // ...

        // Esegui un array di seeders specifici...
        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
            // ...
        ]);
    }
}

In alternativa, puoi istruire Laravel a eseguire automaticamente il seeding del database prima di ogni test che utilizza il trait RefreshDatabase. Puoi fare ciò definendo una proprietà $seed nella tua classe di test base:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    /**
     * Indica se il seeder predefinito deve essere eseguito prima di ogni test.
     *
     * @var bool
     */
    protected $seed = true;
}

Quando la proprietà $seed è impostata su true, il test eseguirà la classe Database\Seeders\DatabaseSeeder prima di ogni test che utilizza il trait RefreshDatabase. Tuttavia, puoi specificare un seeder specifico che deve essere eseguito definendo una proprietà $seeder nella tua classe di test:

use Database\Seeders\OrderStatusSeeder;

/**
 * Esegui uno specifico seeder prima di ogni test.
 *
 * @var string
 */
protected $seeder = OrderStatusSeeder::class;

Asserzioni Disponibili

Laravel fornisce diverse asserzioni per il database per i tuoi test di funzionalità con Pest o PHPUnit. Vedremo ciascuna di queste asserzioni di seguito.

assertDatabaseCount

Verifica che una tabella nel database contenga il numero di record specificato:

$this->assertDatabaseCount('users', 5);

assertDatabaseEmpty

Verifica che una tabella nel database non contenga record:

$this->assertDatabaseEmpty('users');

assertDatabaseHas

Verifica che una tabella nel database contenga record che soddisfano i criteri di ricerca chiave/valore forniti:

$this->assertDatabaseHas('users', [
    'email' => 'sally@example.com',
]);

assertDatabaseMissing

Verifica che una tabella nel database non contenga record che corrispondono ai vincoli di ricerca chiave/valore specificati:

$this->assertDatabaseMissing('users', [
    'email' => 'sally@example.com',
]);

assertSoftDeleted

Il metodo assertSoftDeleted può essere utilizzato per verificare che un determinato modello Eloquent sia stato "soft deleted":

    $this->assertSoftDeleted($user);

assertNotSoftDeleted

Il metodo assertNotSoftDeleted può essere utilizzato per verificare che un determinato modello Eloquent non sia stato "soft deleted":

$this->assertNotSoftDeleted($user);

assertModelExists

Verifica che un determinato modello esista nel database:

use App\Models\User;

$user = User::factory()->create();

$this->assertModelExists($user);

assertModelMissing

Verifica che un determinato modello non esista nel database:

use App\Models\User;

$user = User::factory()->create();

$user->delete();

$this->assertModelMissing($user);

expectsDatabaseQueryCount

Il metodo expectsDatabaseQueryCount può essere chiamato all’inizio del tuo test per specificare il numero totale di query al database che ti aspetti vengano eseguite durante il test. Se il numero effettivo di query eseguite non corrisponde esattamente a questa aspettativa, il test fallirà:

$this->expectsDatabaseQueryCount(5);

// Test...
Lascia un commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *