イントロダクション

Laravelはアプリケーションに送るHTTPリクエストの作成、出力の検査、さらにフォームの入力もスラスラと書けるAPIを提供しています。例として、次に定義するテストを見てください。

<?php

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

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

visitメソッドは、アプリケーションに対するGETリクエストを作成します。seeメソッドは指定されたテキストが、アプリケーションから返されるレスポンスの中に存在することをアサートします。dontSeeメソッドは指定したテキストが、アプリケーションレスポンスの中へ返されていないことをアサートします。これはLaravelで使用できる最も基本的なアプリケーションテストです。

ルートに付けられた名前を使い、GETリクエストを作るvisitRouteメソッドも使用可能です。

$this->visitRoute('profile');

$this->visitRoute('profile', ['user' => 1]);

アプリケーションのテスト

もちろんシンプルに指定したレスポンスの中にテキストが現れるかアサートする以上のことが可能です。リンクのクリックとフォームの埋め込みを見てみましょう。

リンクのテスト

このテストではアプリケーションへのリクエストを作成し、帰ってきたレスポンス中のリンクを「クリック」、それから指定されたURIに到達することをアサートします。たとえば"About Us"のテキスト値を持つレスポンスの中のリンクがあると仮定しましょう。

<a href="/about-us">About Us</a>

では、このリンクをクリックし、正しいページに到達したことをアサートしましょう。

public function testBasicExample()
{
    $this->visit('/')
         ->click('About Us')
         ->seePageIs('/about-us');
}

ユーザが正しい名前付きルートへ到達することを確認する、seeRouteIsメソッドも使用できます。

->seeRouteIs('profile', ['user' => 1]);

フォームのテスト

Laravelはさらにフォームをテストするために多くのメソッドを提供しています。typeselectcheckattachpressメソッドはフォーム入力の全てを操作させてくれます。たとえば、アプリケーションの登録ページにこのフォームがあると考えてください。

<form action="/register" method="POST">
    {{ csrf_field() }}

    <div>
        Name: <input type="text" name="name">
    </div>

    <div>
        <input type="checkbox" value="yes" name="terms"> Accept Terms
    </div>

    <div>
        <input type="submit" value="Register">
    </div>
</form>

このフォームを完全に埋め、結果を確認するテストが書けます。

public function testNewUserRegistration()
{
    $this->visit('/register')
         ->type('Taylor', 'name')
         ->check('terms')
         ->press('Register')
         ->seePageIs('/dashboard');
}

もちろん、フォームにラジオボタンやドロップボックスのような他の入力が含まれていても、同様にそうしたフィールドを簡単に埋めることができます。フォーム操作メソッドのリストを見てください。

メソッド 説明
$this->type($text, $elementName) 指定したフィールドに「タイプ」します。
$this->select($value, $elementName) ラジオボタンかドロップダウンフィールドを「選択」します。
$this->check($elementName) チェックボックスフィールドを「チェック」します。
$this->uncheck($elementName) チェックボックスフィールドを「非チェック」にします。
$this->attach($pathToFile, $elementName) フォームにファイルを「添付」します。
$this->press($buttonTextOrElementName) 指定したテキストか名前のボタンを「押し」ます。

ファイル入力

フォームにfile入力タイプが含まれているならば、attachメソッドを使いフォームにファイルを添付できます。

public function testPhotoCanBeUploaded()
{
    $this->visit('/upload')
         ->attach($pathToFile, 'photo')
         ->press('Upload')
         ->see('Upload Successful!');
}

JSON APIのテスト

さらにLaravelは、JSON APIとそれらのレスポンスをテストするために、多くのヘルパーも用意しています。たとえば、jsongetpostputpatchdeleteメソッドは各HTTP動詞でのリクエストを発行するために使用します。また簡単にデータとヘッダをメソッドに渡すこともできます。手始めに、/userに対するPOSTリクエストを作成し、期待したデータが返ってくることをアサートするテストを書いてみましょう。

<?php

class ExampleTest extends TestCase
{
    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->json('POST', '/user', ['name' => 'Sally'])
             ->seeJson([
                 'created' => true,
             ]);
    }
}

Tip!! seeJsonメソッドは渡された配列をJSONに変換します。次にそのJSONが、JSONレスポンス全体のいずれかに現れるかを確認します。ですから、他のプロパティーがJSONレスポンスに含まれていたとしても、指定した部分が存在する限り、テストはパスします。

厳格な一致の確認

指定した配列がアプリケーションから返されるJSONと厳格に一致するかを確認したい場合は、seeJsonEqualsメソッドを使用してください。

<?php

class ExampleTest extends TestCase
{
    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->json('POST', '/user', ['name' => 'Sally'])
             ->seeJsonEquals([
                 'created' => true,
             ]);
    }
}

構造の一致の確認

JSON形式が特定の構造にピタリと当てはまるかを確認することもできます。このシナリオでは、期待するJSON構造をseeJsonStructureメソッドに渡してください。

<?php

class ExampleTest extends TestCase
{
    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->get('/user/1')
             ->seeJsonStructure([
                 'name',
                 'pet' => [
                     'name', 'age'
                 ]
             ]);
    }
}

上の例ではnameおよび、nameageを持つネストしたpetオブジェクトを受け取ることを期待しています。seeJsonStructureは、レスポンスが余計なキーを含んていても失敗しません。たとえば、petweight属性を持っていても、テストをパスします。

*を使い、戻ってきたJSON構造がリストを持っていること、そして各リストが最低でも持っている属性を指定することもできます。

<?php

class ExampleTest extends TestCase
{
    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        // リスト中の各ユーザが、最低でもid、name、email属性を持っていることをアサートする
        $this->get('/users')
             ->seeJsonStructure([
                 '*' => [
                     'id', 'name', 'email'
                 ]
             ]);
    }
}

*記述法はネストもできます。次の例の場合、JSONレスポンスの各ユーザは指定されている属性を持っており、各ユーザの各ペットも指定されている属性を持っていることを宣言します。

$this->get('/users')
     ->seeJsonStructure([
         '*' => [
             'id', 'name', 'email', 'pets' => [
                 '*' => [
                     'name', 'age'
                 ]
             ]
         ]
     ]);

セッション/認証

Laravelはテスト時にセッションを操作するたくさんのヘルパーも提供しています。1つ目は指定した配列をセッションに保存するwithSessionメソッドです。これはアプリケーションのリクエストをテストする前に、データをセッションにロードしたい場合に便利です。

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $this->withSession(['foo' => 'bar'])
             ->visit('/');
    }
}

もちろん認証済みのユーザのようなユーザ状態をセッションへ保持するのは一般的です。actingAsヘルパーメソッドは現在認証済みのユーザを指定する簡単な手段を提供します。たとえば、モデルファクトリでユーザを生成し、認証してみましょう。

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = factory(App\User::class)->create();

        $this->actingAs($user)
             ->withSession(['foo' => 'bar'])
             ->visit('/')
             ->see('Hello, '.$user->name);
    }
}

ユーザの認証にどのガードを使用するかを指定したい場合、actingAsメソッドの第2引数にガード名を渡します。

$this->actingAs($user, 'api')

ミドルウェアの無効化

アプリケーションをテストするとき、いくつかのテストではミドルウェアを無効にするほうが便利だと気がつくでしょう。これによりミドルウェアに関わらずにルートやコントローラーのテストが可能になります。LaravelはシンプルなWithoutMiddlewareトレイトを用意しており、これを使えば自動的にテストクラスのミドルウェアを無効にできます。

<?php

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

class ExampleTest extends TestCase
{
    use WithoutMiddleware;

    //
}

いくつかのテストメソッドだけでミドルウェアを無効にしたい場合は、withoutMiddlewareメソッドをテストメソッドの中で呼び出してください。

<?php

class ExampleTest extends TestCase
{
    /**
     * 基本的な機能テストの例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->withoutMiddleware();

        $this->visit('/')
             ->see('Laravel 5');
    }
}

カスタムHTTPリクエスト

アプリケーションに対してカスタムHTTPリクエストを作成し、完全なIlluminate\Http\Responseオブジェクトを取得したい場合は、callメソッドを使ってください。

public function testApplication()
{
    $response = $this->call('GET', '/');

    $this->assertEquals(200, $response->status());
}

POSTPUTPATCHリクエストの場合、そのリクエストに入力データの配列を渡すことができます。もちろん、このデーターはRequestインスタンスを使用し、ルートやコントローラーで使用できます。

   $response = $this->call('POST', '/user', ['name' => 'Taylor']);

PHPUnitアサート

PHPUnitテスト用に、数多くの追加アサートメソッドをLaravelは提供しています。

メソッド 説明
->assertResponseOk(); クライアントのレスポンスがOKのステータスコードを受け取ることを宣言
->assertResponseStatus($code); クライアントのレスポンスが指定したコードであることを宣言
->assertViewHas($key, $value = null); レスポンスのビューに指定したデータが含まれていることを宣言
->assertViewHasAll(array $bindings); ビューが指定したデータのリストを持っていることを宣言
->assertViewMissing($key); ビューが指定したデータを含んでいないことを宣言
->assertRedirectedTo($uri, $with = []); クライアントが指定したURIへリダイレクトすることを宣言
->assertRedirectedToRoute($name, $parameters = [], $with = []); クライアントが指定したルートへリダイレクトされることを宣言
->assertRedirectedToAction($name, $parameters = [], $with = []); クライアントが指定したアクションへリダイレクトすることを宣言
->assertSessionHas($key, $value = null); セッションが指定した値を持つことを宣言
->assertSessionHasAll(array $bindings); セッションが指定したリストを持つことを宣言
->assertSessionHasErrors($bindings = [], $format = null); セッションにエラー情報があることを宣言
->assertHasOldInput(); セッションが直前の入力を持つことを宣言
->assertSessionMissing($key); セッションが指定したキーを持っていないことを宣言