本文へ移動
Laravel Tips

データベースのテスト

データベースを使うアプリのテストで、テストごとにデータベースを元に戻す方法・ためしのデータの作り方・データベース用のアサーションを説明します。

データベースを使うアプリのテストでは、「保存したデータが本当に入ったか」「消したデータが本当に無くなったか」を確かめたくなります。Laravel には、そのための道具がそろっています。ためしのデータを簡単に作れる、ファクトリ(ためしのデータを自動で作るしくみ)とシーダー(最初のデータを入れるプログラム)もあります。テストの基本はテストのはじめかたを見てください。

テストのたびにデータベースを元に戻す#

あるテストで入れたデータが、次のテストの結果に影響すると困ります。そこで、テストのたびにデータベースを元に戻します。Illuminate\Foundation\Testing\RefreshDatabase トレイト(クラスに部品を足すしくみ)を、テストのクラスで使うだけです。

Pest で書くとき:

php
<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

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

    // ...
});

PHPUnit で書くとき:

php
<?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('/');

        // ...
    }
}

RefreshDatabase は、データベースの表の作りが最新なら、マイグレーション(データベースの表を作ったり変えたりする手順書)を流しません。代わりに、テストをトランザクション(まとめて取り消せる処理のかたまり)の中で動かします。そのため、このトレイトを使わないテストが入れたデータは、データベースに残ることがあります。

データベースを完全にまっさらにしたいときは、Illuminate\Foundation\Testing\DatabaseMigrations か Illuminate\Foundation\Testing\DatabaseTruncation を使います。ただし、どちらも RefreshDatabase よりずっと遅くなります。

トレイト 説明
RefreshDatabase 表の作りが最新ならそのまま、テストをトランザクションの中で動かす。速い
DatabaseMigrations データベースを完全に作り直す。RefreshDatabase よりずっと遅い
DatabaseTruncation データベースを完全にまっさらにする。RefreshDatabase よりずっと遅い

ファクトリでためしのデータを作る#

テストの前に、データベースにいくつかのデータを入れておきたいことがあります。列の値を1つずつ書かなくても済むように、Eloquent のモデル(データベースの表を、PHP から扱いやすくしたクラス)ごとに標準の値を決めておくしくみが、ファクトリです。

ファクトリの作り方はファクトリのページで説明しています。作ってあれば、テストの中で次のようにモデルを作れます。

Pest で書くとき:

php
use App\Models\User;

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

    // ...
});

PHPUnit で書くとき:

php
use App\Models\User;

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

    // ...
}

シーダーを動かす#

フィーチャーテスト(広い範囲を通して確かめるテスト)の中で、シーダーでデータベースにデータを入れたいときは、seed メソッドを呼びます。何も渡さなければ DatabaseSeeder が動きます。DatabaseSeeder は、ふつうほかのシーダーをすべて動かす役目です。シーダーのクラス名を渡すと、そのシーダーだけを動かせます。

Pest で書くとき:

php
<?php

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

pest()->use(RefreshDatabase::class);

test('orders can be created', function () {
    // DatabaseSeeder を動かす
    $this->seed();

    // 決まったシーダーを動かす
    $this->seed(OrderStatusSeeder::class);

    // ...

    // 複数のシーダーを配列で渡して動かす
    $this->seed([
        OrderStatusSeeder::class,
        TransactionStatusSeeder::class,
        // ...
    ]);
});

PHPUnit で書くとき:

php
<?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
    {
        // DatabaseSeeder を動かす
        $this->seed();

        // 決まったシーダーを動かす
        $this->seed(OrderStatusSeeder::class);

        // ...

        // 複数のシーダーを配列で渡して動かす
        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
            // ...
        ]);
    }
}

RefreshDatabase を使うテストの前に、毎回シーダーを自動で動かすこともできます。土台になるテストのクラスに、Seed という PHP の属性(クラスの前に書く印)を付けます。

php
<?php

namespace Tests;

use Illuminate\Foundation\Testing\Attributes\Seed;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

#[Seed]
abstract class TestCase extends BaseTestCase
{
}

Seed があると、RefreshDatabase を使う各テストの前に Database\Seeders\DatabaseSeeder が動きます。決まったシーダーを動かしたいときは、テストのクラスに Seeder 属性を付けます。

php
<?php

namespace Tests\Feature;

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

#[Seeder(OrderStatusSeeder::class)]
class OrderTest extends TestCase
{
    use RefreshDatabase;

    // ...
}
書き方 説明
$this->seed() DatabaseSeeder を動かす
$this->seed(OrderStatusSeeder::class) 渡したシーダーだけを動かす
$this->seed([...]) 配列で渡した複数のシーダーを動かす
#[Seed] RefreshDatabase を使う各テストの前に DatabaseSeeder を自動で動かす
#[Seeder(クラス名::class)] RefreshDatabase を使う各テストの前に、渡したシーダーを自動で動かす

アサーションの一覧#

Laravel には、データベースを調べる確認の命令(アサーション)があります。Pest でも PHPUnit でも、フィーチャーテストで使えます。

命令 説明
assertDatabaseCount 表のレコード(1行のデータ)の数が、渡した数である
assertDatabaseEmpty 表にレコードが1つも無い
assertDatabaseHas 渡したキーと値に合うレコードが、表にある
assertDatabaseMissing 渡したキーと値に合うレコードが、表に無い
assertSoftDeleted モデルが「ソフトデリート」されている
assertNotSoftDeleted モデルが「ソフトデリート」されていない
assertModelExists モデル(またはモデルの集まり)が、データベースにある
assertModelMissing モデル(またはモデルの集まり)が、データベースに無い
expectsDatabaseQueryCount テスト中に動くクエリ(問い合わせ)の数が、渡した数である

assertDatabaseCount#

表のレコードの数を確かめます。

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

assertDatabaseEmpty#

表にレコードが1つも無いことを確かめます。

php
$this->assertDatabaseEmpty('users');

assertDatabaseHas#

渡したキーと値に合うレコードが、表にあることを確かめます。

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

assertDatabaseMissing#

渡したキーと値に合うレコードが、表に無いことを確かめます。

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

assertSoftDeleted#

ソフトデリート(データを本当には消さず、「消した印」だけ付ける方法)されたことを確かめます。

php
$this->assertSoftDeleted($user);

assertNotSoftDeleted#

ソフトデリートされていないことを確かめます。

php
$this->assertNotSoftDeleted($user);

assertModelExists#

モデル、またはモデルの集まりが、データベースにあることを確かめます。

php
use App\Models\User;

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

$this->assertModelExists($user);

assertModelMissing#

モデル、またはモデルの集まりが、データベースに無いことを確かめます。

php
use App\Models\User;

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

$user->delete();

$this->assertModelMissing($user);

expectsDatabaseQueryCount#

テストの最初で呼んで、そのテストで動くデータベースへの問い合わせ(クエリ)の数を決めます。実際の数が1つでも違うと、テストは失敗します。

php
$this->expectsDatabaseQueryCount(5);

// Test...

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧