Laravelでのユーザー認証は私のブログの中では最も人気のあるトピックです。今回は、私のLaravelの日本語のレポジトリ(Laravel 5.4)のコードをもとに、ユーザー認証のテストに取り組んでいきます。
テストの種類
テストと言っても、いくつか種類があり、Laravel5.4からはtestsのディレクトリ構造も変わり、
tests
├── CreatesApplication.php
├── Feature
│   └── ExampleTest.php
├── TestCase.php
└── Unit
    └── ExampleTest.php
のようにFeatureとUnitの2つのサブディレクトリができました。
Unitには、一般的にはユニットテストと呼ばれるもので、大方は画面の表示を伴わないModelのメソッドに対するテストを作成します。一方、Featureには、機能テストやアクセプタンステストとも言われ、複数のクラスの複数のメソッドが関わる主にコントローラの機能を検証するためで、あたかもユーザーがテストするようなテストを作成します。
私の今までの開発では、比較的作成しやすいUnitテストが主で、Featureテストは皆無に近く、人間のテスターがその仕事を行っています。人間をFeatureテストに置き換える予定はないですが、Laravelが提供するテストの環境がFeatureテストを作成しやすくなってきているので、この機会に習得しようということです。
Laravel5.4では、Featureテストのために、2つのテストのフレームワークが提供されています。
- HTTPテスト:ブラウザを通さないエンドポイントのテスト
 - ブラウザテスト(Dusk):ブラウザキットを利用したテスト
 
ここでは、まず、追加のパッケージのインストールも要らない、高速なHTTPテストを作成していきます。
準備
github.comにおいて以下のブランチを用意したので利用してください。
https://github.com/lotsofbytes/larajapan/tree/5.4-test
インストールは以下を参照してください。
Laravelの日本語のレポジトリ(Laravel 5.4)
設定したら、必ず以下を実行してブランチを変えてください。
$ git checkout l54-test
また、そこでは、phpunit.xmlを編集も必要です。以下を参考にしてください。
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="APP_URL" value="http://localhost"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="DB_HOST" value="localhost"/>
        <env name="DB_DATABASE" value="larajapan_test"/>
        <env name="DB_USERNAME" value="test"/>
        <env name="DB_PASSWORD" value="password"/>
        <env name="MAIL_DRIVER" value="log" />
        <env name="QUEUE_DRIVER" value="sync"/>
    </php>
</phpunit>
テストのDBは.envで設定しているものと違うDBが必要なことに注意してください。
最初のテスト
もとからあるtests/Feature/ExampleTest.phpのファイルを、LoginTest.phpと改名して以下のように編集します。
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class LoginTest extends TestCase
{
    /** @test */
    public function user_can_view_login()
    {
        $response = $this->get('login');
        $response->assertStatus(200);
    }
    /** @test */
    public function unauthenticated_user_cannot_view_home()
    {
        $this->get('home')
        	->assertRedirect('login');
    }
}
最初のテストuser_can_view_loginは、ログイン画面が閲覧できるかどうかのテストです。
返ってくるHTTPのステータスのコードが200なら、成功ということです。これが404(ページが見つかりません)とかだと何かがおかしいということになります。
次のテストunauthenticated_user_cannot_view_homeは、認証が必要なホームページに、認証もなしにアクセスしてみます。もちろん、アクセスできないでログイン画面にリダイレクトされるはずです。
ここ、メソッドが連結されていることに気づきましたか?
最初のテストの例のように、以下のよう2つの文に分けても書くこともできます。
$response = $this->get('home');
$response->assertRedirect('login');
これらのテストの実行ですが、Laravelのインストールにより、すでにvendorのディレクトリにphpunitのパッケージもインストールされています。
ということで、
$ vendor/bin/phpunit PHPUnit 5.7.23 by Sebastian Bergmann and contributors. ... 3 / 3 (100%) Time: 171 ms, Memory: 10.00MB OK (3 tests, 4 assertions)
と実行してテストは皆成功となります。3 testsとあるのは、app/tests/Unit/ExampleTestがあるからです。
以下のようにフィルタを書ければ、LoginTestの中のテストだけや、user_can_view_loginの1つテストだけの実行も可能です。
$ vendor/bin/phpunit --filter=LoginTest HPUnit 5.7.23 by Sebastian Bergmann and contributors. .. 2 / 2 (100%) Time: 157 ms, Memory: 10.00MB OK (2 tests, 3 assertions) $ vendor/bin/phpunit --filter=user_can_view_login PHPUnit 5.7.23 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 111 ms, Memory: 10.00MB OK (1 test, 1 assertion)メルマガ購読の申し込みはこちらから。
