【Laravel】フォームリクエストバリデーションのテストコード作成

# はじめに
Laravelには、フォームリクエストバリデーションというものがあります。
フォームリクエストバリデーションは、簡単に言うとLaravel標準で用意されているバリデーションとは別に、
自身でバリデーションをカスタムできる機能のことです。
バリデーションのテストは、実際に画面で入力して、手動でテストすることもできますが、
数が多くなってくると大変ですし、例えば、最大文字数255文字というルールがある場合、
手打ちで255文字の文字列を打つのはなかなか大変ですし、そもそも本当に255文字入力しているのかということも分かりづらいです。
今回、そういった問題を解消するために、バリデーションのテストコードの書き方を紹介したいと思います。

# 環境
- 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（今回DBは使わないですが、一応。。。）

# フォームリクエストバリデーションの作成
フォームリクエストを作成し、その中にバリデーションのルールを記載していきます。

## フォームリクエストクラスの作成
```
$ php artisan make:request CustomRequest
```
上記コマンドでCustomRequestクラスを作成します。
`app/Http/Requests/` 配下にファイル( `CustomRequest.php` )が作成されています。

## フォームリクエストクラスにバリデーションのルールを設定
以下のようにソースを修正します。

```app/Http/Requests/CustomRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CustomRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required|max:255',
        ];
    }
}
```
`rules` メソッドに独自のバリデーションルールを記載しています。
`title` という項目に対し、 `required` と `max:255` という二つのルールを設定しました。

| ルール|意味|
|:-----------------|:------------------|
| required|必須項目|
|max:255|最大255文字まで入力可能| 
 
# テストコード作成
次に先ほど作成した、フォームリクエストクラスのテストコードを作成します。

## フォームリクエストクラスのテストコード作成
```
$ php artisan make:test CustomRequestTest
```
上記コマンドでCustomRequestTestクラスを作成します。
デフォルトでは、 `tests/Feature` 以下に作成されますが、
リクエストのテストということを分かりやすくするため、 `tests` 配下に `Requests` ディレクトリを作成します。
そして、その配下に、先ほど作成したファイルを移動します。
`tests/Requests/CustomRequestTest.php` 

## テストコード編集
以下のようにテストコードを編集します。

```tests/Requests/CustomRequestTest.php
<?php

namespace Tests\Requests;

use Tests\TestCase;
use Illuminate\Support\Facades\Validator;
use App\Http\Requests\CustomRequest;

class CustomRequestTest extends TestCase
{
    /**
     * カスタムリクエストのバリデーションテスト
     *
     * @param string 項目名
     * @param string 値
     * @param boolean 期待値(true:バリデーションOK、false:バリデーションNG)
     * @dataProvider dataproviderExample
     */
    public function testExample($item, $data, $expect)
    {
        //入力項目（$item）とその値($data)
        $dataList = [$item => $data];

        $request = new CustomRequest();
        //フォームリクエストで定義したルールを取得
        $rules = $request->rules();
        //Validatorファサードでバリデーターのインスタンスを取得、その際に入力情報とバリデーションルールを引数で渡す
        $validator = Validator::make($dataList, $rules);
        //入力情報がバリデーショルールを満たしている場合はtrue、満たしていな場合はfalseが返る
        $result = $validator->passes();
        //期待値($expect)と結果($result)を比較
        $this->assertEquals($expect, $result);
    }

    public function dataproviderExample()
    {
        return [
            '正常' => ['title', 'タイトル', true],
            '必須エラー' => ['title', '', false],
            //str_repeat('a', 256)で、256文字の文字列を作成(aが256個できる)
            '最大文字数エラー' => ['title', str_repeat('a', 256), false],
        ];
    }

}
```
説明はコメントに記載した通りになります。
データプロバイダ( `dataproviderExample` )で `testExample` に渡す引数（詳細はPHPDoc参照）を指定しています。 
※データプロバイダについて、わからない場合は、こちらを参考にしてください。→[データプロバイダ](https://phpunit.de/manual/current/ja/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers)

## phpunit.xmlの編集
先ほど、`tests/Requests` 配下にテストコードを移動しましたが、
Requests配下にあるものがテストコードだよ、ということを認識させるために、 `phpunit.xml` を編集する必要があります。

```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 Tests">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit Tests">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>

        <testsuite name="Unit Tests">
            <directory suffix="Test.php">./tests/Requests</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
    </php>
</phpunit>
```

`phpunit.xml` 自体は、Laravelのプロジェクトを作成した時点で用意されており、
今回追加したのは、以下の部分になります。

```xml
        <testsuite name="Unit Tests">
            <directory suffix="Test.php">./tests/Requests</directory>
        </testsuite>
```
`./tests/Requests` 配下にあるのは、テストコードですよ、ということが認識されるようになります。

# テストコード実行
以下のようにしてテストコードを実行します。

```
$ vendor/bin/phpunit

PHPUnit 5.7.19 by Sebastian Bergmann and contributors.

.....                                                               5 / 5 (100%)

Time: 2.95 seconds, Memory: 12.00MB

OK (5 tests, 5 assertions)
```
テストが実行され、成功のメッセージが出力されました。

# まとめ
今回は、フォームリクエストバリデーションのテストコードを作成しました。
時間を見つけて、他にもテストコードの書き方を記事にしていきたいと思います。