Laravel 5.3 データベースのテスト

イントロダクション

Laravelでは、データベースを駆動するアプリケーションのテストを簡単にできる、便利で様々なツールを用意しています。その一つは、指定した抽出条件に一致するデータがデータベース中に存在するかをアサートする、seeInDatabaseヘルパです。たとえば、userテーブルの中にemailフィールドがsally@example.comの値のレコードが存在するかを確認したいとしましょう。次のようにテストできます。

public function testDatabase()
{
    // アプリケーションを呼び出す…

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

もちろん、seeInDatabaseメソッドやその他のヘルパは、利便性のために用意しています。PHPUnitの組み込みアサートメソッドは、テストで自由に使用できます。

各テスト後のデータベースリセット

前のテストデータが、それに引き続くテストへ影響をあたえないように、各テストが終了するごとにデータベースをリセットするのは、時に便利です。

マイグレーションの使用

一つのアプローチは、それぞれのテストの後にデータベースをロールバックし、次のテストの前にマイグレーションする方法です。Laravelはこれを自動的に処理するために、シンプルなDatabaseMigrationsトレイトを用意しています。テストクラスでこのトレイトを使用するだけで、すべて処理されます。

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

トランザクションの使用

データベースをリセットするもう一つのアプローチは、各テストケースをデータベーストランザクションでラップしてしまうことです。Laravelはこれを自動的に処理する、便利なDatabaseTransactionsトレイトを用意してます。

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

Note: デフォルトでは、このトレイトは、トランザクション中のデフォルトデータベース接続をラップしているだけです。もし、アプリケーションで複数のデータベース接続を使用している場合は、テストクラスの$connectionsToTransactプロパティを定義する必要があります。このプロパティはトランザクションで実行する接続名の配列を指定します。

ファクトリの記述

テスト時、何件かのレコードをデータベースに挿入する必要が起きることがあります。こうしたテストデータを作る時に、手動でそれぞれのカラムへ値を指定する代わりに、Laravelでは「ファクトリ」を使用しEloquentモデルの各属性にデフォルトを設定できます。手始めに、アプリケーションのdatabase/factories/ModelFactory.phpファイルを見てください。このファイルには最初からファクトリの定義が含まれています。

$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

ファクトリで定義しているクロージャの中から、モデルの全属性に対するデフォルトのテスト値を返しています。このクロージャはFaker PHPライブラリーのインスタンスを受け取っており、これはテストのための多用なランダムデータを生成するのに便利です。

もちろん追加のファクトリをModelFactory.phpに自由に追加できます。系統立てるためには各モデルのファクトリーファイルを追加したほうが良いでしょう。たとえば、database/factoriesディレクトリの中へUserFactory.phpCommentFactory.phpファイルを作成します。 factoriesディレクトリ中のファイルは、自動的にLaravelにより読みこまれます。

ファクトリステート

ステートにより、どんな組み合わせのモデルファクトリに対しても、変更を取り消す定義を行うことができます。たとえば、Userモデルがデフォルトの属性値を変更する、delinquentステートを持っているとしましょう。stateメソッドを使い、状態の変更を定義できます。

$factory->state(App\User::class, 'delinquent', function ($faker) {
    return [
        'account_status' => 'delinquent',
    ];
});

ファクトリの使用

モデルの生成

ファクトリを定義し終えたら、テストかデータベースのシーディング(初期値設定)ファイルの中で、グローバルなfactory関数を使用してモデルインスタンスを生成できます。では、モデル生成の例をいくつか見てみましょう。最初はmakeメソッドでモデルを生成し、データベースには保存しないでみましょう。

public function testDatabase()
{
    $user = factory(App\User::class)->make();

    // モデルをテストで使用…
}

さらにモデルのコレクションや指定したタイプのモデルも生成できます。

// App\Userインスタンスを3つ生成
$users = factory(App\User::class, 'admin', 3)->make();

ステートの適用

$users = factory(App\User::class, 5)->states('delinquent')->make();

$users = factory(App\User::class, 5)->states('premium', 'delinquent')->make();

$users = factory(App\User::class, 5)->states('premium', 'deliquent')->make();

属性のオーバーライド

モデルのデフォルト値をオーバーライドしたい場合は、makeメソッドに配列で値を渡してください。指定した値のみ置き換わり、残りの値はファクトリで指定したデフォルト値のまま残ります。

$user = factory(App\User::class)->make([
    'name' => 'Abigail',
]);

モデルの保存

createメソッドはモデルインスタンスを生成するだけでなく、Eloquentのsaveメソッドを使用しデータベースへ保存します。

public function testDatabase()
{
    // 一つのApp\Userインスタンスを作成
    $user = factory(App\User::class)->create();

    // 3つのApp\Userインスタンスを作成
    $users = factory(App\User::class, 3)->create();

    // モデルをテストで使用する…
}

createメソッドに配列で値を渡すことで、モデルの属性をオーバーライドできます。

$user = factory(App\User::class)->create([
    'name' => 'Abigail',
]);

リレーション

以下の例では、生成したモデルにリレーションを付けています。複数モデルの生成にcreateメソッドを使用する場合、インスタンスのコレクションが返されます。そのため、コレクションで使用できるeachなどの便利な関数が利用できます。

$users = factory(App\User::class, 3)
           ->create()
           ->each(function ($u) {
                $u->posts()->save(factory(App\Post::class)->make());
            });

リレーションと属性クロージャ

クロージャ属性をファクトリ定義の中で使い、モデルとのリレーションを追加することもできます。たとえば、Postを作成する時に、新しいUserインスタンスも作成したい場合は、以下のようになります。

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        }
    ];
});

さらに、クロージャは評価済みのファクトリーの配列を受け取ることもできます。

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        },
        'user_type' => function (array $post) {
            return App\User::find($post['user_id'])->type;
        }
    ];
});

ドキュメント章別ページ

開発環境
ビューとテンプレート
Artisanコンソール
公式パッケージ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる