LaravelではIlluminate\Contracts\Validation\Rule
を継承したクラスを用いてカスタムなバリデーションを作成することができます。そしてサービスプロバイダに登録することで、FormRequestで文字列で指定することでリクエストのバリデーションを拡張できます。
ただしこの様な独自コードはきちんとユニットテストをすることが大切です。Laravelではこのカスタムバリデーションを簡単にユニットテストをすることができます。
とりあえず以下の様な郵便番号のバリデーションを作成したとします。7桁のハイフンなしの数字が郵便番号の形式とします。
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Zipcode implements Rule{
public function passes($attribute, $value)
{
return preg_match('/^[0-9]{3}-?[0-9]{4}$/', $value);
}
public function message(){
return '郵便番号は7桁の半角数字で入力してください。';
}
}
ひとまず tests/Unit/Rules.php
というものを作成します。
namespace Tests\Unit;
use App\Rules\Zipcode;
use Illuminate\Foundation\Testing\TestCase;
use Tests\CreatesApplication;
use Illuminate\Support\Facades\Validator;
use \Illuminate\Validation\ValidationException;
class Rules extends TestCase{
use CreatesApplication;
public function test_zipcode_validation(){
$tests = [
'1234567'=>true,
'0012344'=>true,
'0012340'=>true,
'12345678'=>false,
'123456'=>false,
'1234 56'=>false,
'1234a56'=>false,
'1234_56'=>false,
];
foreach($tests as $key => $condition){
try{
Validator::make(['test'=>$key],[
'test'=> new Zipcode()
])->validate();
$this->assertTrue($condition===true);
}catch(ValidationException $e){
$this->assertFalse($condition);
}
}
}
}
バリデーションテストでは正しい形式は正しいと判断(ポジティブテスト)し、間違っているものは間違っていると判断(ネガティブテスト)できているかをテストします。 もしも正しいのに間違っていると判断したり、間違っているのに正しいとなったらテストが失敗する様になっています。
ここでバリデーションテストの詳細を解説します。
最初にテストしたいバリデーションのインスタンス、そしてバリデーターインスタンスを作成します。
Validator::make(['test'=>$key],[
'test'=> new Zipcode()
])->validate();
Validator
ではmake()
を使用して第一引数に、バリデーションをする値とキーを設定します。第二引数にはバリデーションのキーとバリデーションインスタンスを指定します。
いろいろなパターンをテストするため以下の様に配列でテストパターンと予期する正誤を設定します。Trueはバリデーション通過で、Falseはバリデーション違反(間違った形式)であることを示します。
$tests = [
'1234567'=>true,
'0012344'=>true,
'0012340'=>true,
'12345678'=>false,
'123456'=>false,
'1234 56'=>false,
'1234a56'=>false,
'1234_56'=>false,
];
そしてforeachでそれぞれチェックします。
foreach($tests as $key => $condition){
try{
Validator::make(['test'=>$key],[
'test'=> new Zipcode()
])->validate();
$this->assertTrue($condition===true);
}catch(ValidationException $e){
$this->assertFalse($condition);
}
}
validate()
メソッドは失敗するとValidationException
を投げます。そのため例外処理でValidationException
をキャッチします。正しい形式を正しいと判断できれば$this->assertTrue($condition===true);
となり、まちがった形を間違っていると判断できればキャッチして$this->assertFalse($condition);
でアサートされます。
php artisan test
にてテストを行い問題なければそのまま通過します。テストは以上の方法でいろんなパターンをテストできます。パターンは思いついたものを配列に書いてもいいですし、プログラム的に大量に配列を生成してもいいかもしれません。まとめると
ValidationException
を用いて間違っている形を識別assertTrue
とassertFalse
で正しく判断できているかをアサートこんな感じです。私はこのテストで結構救われたので、バリデーションを作った時は必ずユニットテストをしましょう。