Laravel 5.4で導入されたLaravel Duskをテスト後にDBリセットさせるようにして試してみた


はじめに

Laravel 5.4で導入されたブラウザテストのためのLaravel Duskを使ってみました。
※公式ドキュメント
Laravel Duskは、簡単なコマンドでテストコードを用意できたり、
テストがこけた時にスクリーンショットを撮ってくれたり、色々と便利です。
今回は、Laravel自体はすでに導入済みということを想定して、Laravel Duskを導入する手順からまとめました。

環境

  • OS X El Capitan 10.11.6
  • PHP 7.0.18
  • laravel/framework 5.4.19
  • laravel/dusk 1.1.0
  • MySQL 5.7.18

Laravel Duskの導入

公式ドキュメントの方法に沿って、composerを使って導入しました。
下記コマンドで composer.json に自動で追記してくれ、Laravel Duskの導入までやってくれます。

$ composer require laravel/dusk

Laravel Duskを使用するための準備

Laravel Duskインストール

artisanコマンドでインストールします。

$ php artisan dusk:install

インストールが成功すると、 /tests 配下に以下のファイルが作成されます。

/tests/Browser/ExampleTest.php
/tests/Browser/Pages/HomePage.php
/tests/Browser/Pages/Page.php
/tests/Browser/console/.gitignore
/tests/Browser/screenshots/.gitignore
/tests/DuskTestCase.php

/tests/Browser/ExampleTest.php は、デフォルトで作成されるLaravelのTOP画面のテストです。
テストでは、TOP画面(/)にアクセスし、「Laravel」という文字があることを確認している簡単なテストです。

/tests/Browser/ExampleTest.php
<?php

namespace Tests\Browser;

use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends DuskTestCase
{
    /**
     * A basic browser test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->assertSee('Laravel');
        });
    }
}

標準の認証機能の導入

今回は、ログイン画面でのブラウザテストをしたいので、Laravelが標準で用意している認証機能を入れます。
これで基本的な認証機能が使えるようになります。
※すでに認証機能を入れている場合、この手順は不要です。

$ php artisan make:auth

ログイン画面のテストコード作成

下記artisanコマンドでテストコードを作成してくれます。

$ php artisan dusk:make LoginTest

以下のテストコードが作成されます。

/tests/Browser/LoginTest.php
<?php
namespace Tests\Browser;
use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class LoginTest extends DuskTestCase
{
    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function testExample()
    {
        $user = factory(User::class)->create([
            'email' => '[email protected]',
        ]);
        $this->browse(function ($browser) use ($user) {
            $browser->visit('/login')
                    ->type('email', $user->email)
                    ->type('password', 'secret')
                    ->press('Login')
                    ->assertPathIs('/home');
        });
    }
}

factory(User::class)->create でテスト用のユーザを作成し、ログイン後に、 ホーム画面(/home)に遷移していることを確認するテストです。
ただ、このままだとテスト用に作成したデータがDB上に残ったままになります。
テストを何度も実行することを考えると不便なので、テスト後にデータベースをリセットするように以下のようにコードを修正します。

/tests/Browser/LoginTest.php
<?php
namespace Tests\Browser;
use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class LoginTest extends DuskTestCase
{
    use DatabaseMigrations;

    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function testExample()
    {
        $user = factory(User::class)->create([
            'email' => '[email protected]',
        ]);
        $this->browse(function ($browser) use ($user) {
            $browser->visit('/login')
                    ->type('email', $user->email)
                    ->type('password', 'secret')
                    ->press('Login')
                    ->assertPathIs('/home');
        });
    }
}

上記のように use DatabaseMigrations; を追加するだけです。
これにより、テストの毎にマイグレーションを実行し、テストが終了した後には、DBをリセットしてくれます。
なので、あらかじめテスト用のDBを作成しておくだけで十分です。

環境ファイルの準備

テスト実行時は、 .env に記載されている情報を元にテストが実行されますが、
テスト用に内容を書き換える必要がある場合、その都度書き換えるのがめんどいので、テスト用の環境ファイルを用意します。
名称は、 .env.dusk.local とします。
local の部分が環境になり、今回はlocal環境のためこの名称としています。

env.dusk.local(一部抜粋)
APP_URL=http://localhost

APP_URLは、実際にブラウザで画面にアクセスするときのURLと同じ値を設定します。

テスト実行

いよいよテストを実行します。
以下のようにしてテストを実行することができます。

$ php artisan dusk

PHPUnit 5.7.19 by Sebastian Bergmann and contributors.

..                                                                  2 / 2 (100%)

Time: 22.77 seconds, Memory: 14.00MB

OK (2 tests, 2 assertions)

こちらは正常終了した場合の結果です。
せっかくなので、失敗した時にどうなるか見てみます。

/tests/Browser/LoginTest.php
<?php
namespace Tests\Browser;
use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class LoginTest extends DuskTestCase
{
    use DatabaseMigrations;

    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function testExample()
    {
        $user = factory(User::class)->create([
            'email' => '[email protected]',
        ]);
        $this->browse(function ($browser) use ($user) {
            $browser->visit('/login')
                    ->type('email', $user->email)
                    ->type('password', 'secret')
                    ->press('Login')
                    ->assertPathIs('/home')
                    ->assertSee('あいうえお');
        });
    }
}

assertSee('あいうえお') を追加しました。
これは、ホーム画面で「あいうえお」という文字列が存在するかを確認するためのメソッドです。
この状態で実行してみます。

$ php artisan dusk

PHPUnit 5.7.19 by Sebastian Bergmann and contributors.

.F                                                                  2 / 2 (100%)

Time: 21.74 seconds, Memory: 14.00MB

There was 1 failure:

1) Tests\Browser\LoginTest::testExample
Did not see expected text [あいうえお] within element [body].
Failed asserting that false is true.

/vendor/laravel/dusk/src/Concerns/MakesAssertions.php:239
/vendor/laravel/dusk/src/Concerns/MakesAssertions.php:210
/tests/Browser/LoginTest.php:34
/vendor/laravel/dusk/src/TestCase.php:91
/tests/Browser/LoginTest.php:35

FAILURES!
Tests: 2, Assertions: 3, Failures: 1.

テストが失敗しました。
Did not see expected text [あいうえお] within element [body]. と出ています。
ホーム画面に「あいうえお」という文字列はありませんよということですね。
次にスクリーンショットを見てみます。
/tests/Browser/screenshots/failure-testExample-0.png のように、
/tests/Browser/screenshots以下にエラー時のスクリーンショットが作成されます。


実際にログインした後のホーム画面のスクリーンショットです。
スクリーンショットを見ると、確かに「あいうえお」という文字列が無いことが分かります。

まとめ

今回は、Laravel Duskの特徴を簡単に紹介させていただきました。
他にもLaravelには便利な機能がいっぱいあるので、時間を見つけて記事を書いてみたいと思います。