Lang x Lang

Database Testing

Table of Contents

Introduction

Laravel は、database 駆動 types の application の test を容易にするための、様々な便利なツールとアサーションを提供しています。加えて、Laravel モデルの factories ーやシーダーは、application の Eloquent モデルやリレーションシップを使用した testdatabase レコードの作成を簡単にします。以下のドキュメンテーションでは、これらの強力な機能について全て説明します。

テストのたびに Database をリセットする

これ以上進む前に、各テストの後にどのように reset を行い、前のテストの data が次のテストに干渉しないように database をリセットするかについて説明しましょう。Laravel に含まれる Illuminate\Foundation\Testing\RefreshDatabase トレイトがこれを処理してくれます。テストの class でこのトレイトを使うだけです:

<?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;

    /**
     * A basic functional test example.
     */
    public function test_basic_example(): void
    {
        $response = $this->get('/');

        // ...
    }
}

Illuminate\Foundation\Testing\RefreshDatabase トレイトは、 schema が最新の場合、 database を migrate しません。代わりに、 database transaction 内でテストのみを実行します。そのため、このトレイトを使用しないテストケースによって database に追加されたレコードは、 database に存在し続ける可能性があります。

あなたが database を完全に reset したい場合は、代わりにIlluminate\Foundation\Testing\DatabaseMigrations または Illuminate\Foundation\Testing\DatabaseTruncation の特性を使用することができます。しかし、これらの options は、RefreshDatabase の特性よりもかなり遅いです。

Model Factories

testing を行う際には、testing を実行する前に database にいくつかのレコードを挿入する必要があるかもしれません。testingdata を作成する際に各列の value を手動で指定する代わりに、Laravel では、Eloquent modelsごとに一連の default 属性を定義することができます。これはmodelfactory ーを使用して行います。

modelfactory ーの作成と活用について更に詳しく学ぶためには、完全なmodel factory ドキュメンテーションをご覧ください。model factory を定義すると、test 内で factory を活用して models を作成することができます。

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();

    // ...
}

Running Seeders

database seedersを使用して feature テスト中に database を満たしたい場合、seed method を呼び出すことができます。default では、seed method はDatabaseSeederを実行し、他のすべてのシーダーを実行するはずです。または、特定のシーダー class 名をseed method に渡すこともできます:

<?php

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

uses(RefreshDatabase::class);

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

    // Run a specific seeder...
    $this->seed(OrderStatusSeeder::class);

    // ...

    // Run an array of specific seeders...
    $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 creating a new order.
     */
    public function test_orders_can_be_created(): void
    {
        // Run the DatabaseSeeder...
        $this->seed();

        // Run a specific seeder...
        $this->seed(OrderStatusSeeder::class);

        // ...

        // Run an array of specific seeders...
        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
            // ...
        ]);
    }
}

あるいは、RefreshDatabase トレイトを使用する各 test の前に Laravel に自動的に seed を database に行うよう指示することもできます。これは、ベース test class 上に $seed プロパティを定義することで実現できます:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    /**
     * Indicates whether the default seeder should run before each test.
     *
     * @var bool
     */
    protected $seed = true;
}

$seedプロパティがtrueの場合、test はRefreshDatabaseトレイトを使用する各 test の前にDatabase\Seeders\DatabaseSeeder class を実行します。ただし、test class 上の$seederプロパティを定義することで実行するべき特定のシーダーを指定することができます。

use Database\Seeders\OrderStatusSeeder;

/**
 * Run a specific seeder before each test.
 *
 * @var string
 */
protected $seeder = OrderStatusSeeder::class;

Available Assertions

Laravel は、Pest またはPHPUnit の feature test のためのいくつかの database アサーションを提供します。以下でこれらのアサーションのそれぞれについて議論します。

assertDatabaseCount

database のテーブルに指定された数のレコードが含まれていることを Assert します:

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

assertDatabaseHas

指定されたキー/ value query 制約に一致するレコードを database のテーブルが含んでいると Assert します:

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

assertDatabaseMissing

database 内のテーブルが与えられた key/ value query 制約に一致するレコードを含まないことを Assert します:

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

assertSoftDeleted

assertSoftDeletedmethod は、特定の Eloquent model が "soft deleted"されたことを assert するために使用できます。

$this->assertSoftDeleted($user);

assertNotSoftDeleted

assertNotSoftDeleted method は、特定の Eloquent model が "soft deleted" されていないことを assert するために使用できます。

$this->assertNotSoftDeleted($user);

assertModelExists

指定された model が database に存在することを Assert します:

use App\Models\User;

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

$this->assertModelExists($user);

assertModelMissing

指定された model が database に存在しないと Assert します:

use App\Models\User;

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

$user->delete();

$this->assertModelMissing($user);

expectsDatabaseQueryCount

test の開始時に、test 中に実行されることを予期する databasequeries の合計数を指定するために、expectsDatabaseQueryCountmethod を呼び出すことができます。実際に実行された queries の数がこの期待 values と一致しない場合、test は失敗します。

$this->expectsDatabaseQueryCount(5);

// Test...

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use