データベースのテスト
データベースを使うアプリのテストで、テストごとにデータベースを元に戻す方法・ためしのデータの作り方・データベース用のアサーションを説明します。
データベースを使うアプリのテストでは、「保存したデータが本当に入ったか」「消したデータが本当に無くなったか」を確かめたくなります。Laravel には、そのための道具がそろっています。ためしのデータを簡単に作れる、ファクトリ(ためしのデータを自動で作るしくみ)とシーダー(最初のデータを入れるプログラム)もあります。テストの基本はテストのはじめかたを見てください。
テストのたびにデータベースを元に戻す#
あるテストで入れたデータが、次のテストの結果に影響すると困ります。そこで、テストのたびにデータベースを元に戻します。Illuminate\Foundation\Testing\RefreshDatabase トレイト(クラスに部品を足すしくみ)を、テストのクラスで使うだけです。
Pest で書くとき:
<?php
use Illuminate\Foundation\Testing\RefreshDatabase;
pest()->use(RefreshDatabase::class);
test('basic example', function () {
$response = $this->get('/');
// ...
});
PHPUnit で書くとき:
<?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 で書くとき:
use App\Models\User;
test('models can be instantiated', function () {
$user = User::factory()->create();
// ...
});
PHPUnit で書くとき:
use App\Models\User;
public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();
// ...
}
シーダーを動かす#
フィーチャーテスト(広い範囲を通して確かめるテスト)の中で、シーダーでデータベースにデータを入れたいときは、seed メソッドを呼びます。何も渡さなければ DatabaseSeeder が動きます。DatabaseSeeder は、ふつうほかのシーダーをすべて動かす役目です。シーダーのクラス名を渡すと、そのシーダーだけを動かせます。
Pest で書くとき:
<?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
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
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
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#
表のレコードの数を確かめます。
$this->assertDatabaseCount('users', 5);
assertDatabaseEmpty#
表にレコードが1つも無いことを確かめます。
$this->assertDatabaseEmpty('users');
assertDatabaseHas#
渡したキーと値に合うレコードが、表にあることを確かめます。
$this->assertDatabaseHas('users', [
'email' => 'sally@example.com',
]);
assertDatabaseMissing#
渡したキーと値に合うレコードが、表に無いことを確かめます。
$this->assertDatabaseMissing('users', [
'email' => 'sally@example.com',
]);
assertSoftDeleted#
ソフトデリート(データを本当には消さず、「消した印」だけ付ける方法)されたことを確かめます。
$this->assertSoftDeleted($user);
assertNotSoftDeleted#
ソフトデリートされていないことを確かめます。
$this->assertNotSoftDeleted($user);
assertModelExists#
モデル、またはモデルの集まりが、データベースにあることを確かめます。
use App\Models\User;
$user = User::factory()->create();
$this->assertModelExists($user);
assertModelMissing#
モデル、またはモデルの集まりが、データベースに無いことを確かめます。
use App\Models\User;
$user = User::factory()->create();
$user->delete();
$this->assertModelMissing($user);
expectsDatabaseQueryCount#
テストの最初で呼んで、そのテストで動くデータベースへの問い合わせ(クエリ)の数を決めます。実際の数が1つでも違うと、テストは失敗します。
$this->expectsDatabaseQueryCount(5);
// Test...
関連するページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。