[Laavel 테스트] 양식에 여러 항목의 유효성 검사를 요청하는 테스트 코드를 써 보았습니다.

역사를 갱신하다


2020/11/2

  • RegisterRequestTest.php 서류의 배치 위치를 tests/Requests/의 부하에서 tests/Unit/Requests/
  • 로 변경한다.

  • 편집phpunit.xml에 대한 설명 수정
  • 테스트 용례의 샘플 메일 주소를 [email protected]test.com과aaa.com을 테스트 데이터에 쓰지 마세요.
  • 로 수정

    개시하다


    지금은 개인 개발에서 라벨을 이용해'모두의 조합 취합 사이트'를 만들고 있다.
    이번 개발은 처음으로 테스트 코드를 썼는데 발리 테스트 코드는 참고[Laavel] 양식에서 검증을 요청하는 테스트 코드 제작로 실시되었다.
    (포맷 팟캐스트가 뭐야!? 이러면 Laavel의 발리에서 테이블 요청 사용 참고 가치가 있어!발리 효과도 컨트롤러에 다 적혀있을 때가 그립다.)
    자체적으로 실시하면 약간 막힌다. 위에서 보도한 샘플 코드는 하나의 프로젝트의 유효성인데 이번에는 여러 항목(사용자 로그인의 유효성이 필요하기 때문에 name,email,password,RegisterRequest 세 개)의 유효성이 필요하다.
    팩스의 여지가 많을 거라고 생각합니다. 이번에는 실장한 여러 항목의 유효성을 소개하겠습니다.
    (※ 95%는 [Laavel] 양식에서 검증을 요청하는 테스트 코드 제작의 내용을 참고했습니다!감사합니다!)

    컨디션


    Laravel 7.26.1
    PHP 7.4.11

    창 만들기 요청


    $ php artisan make:request RegisterRequest
    
    사용자 등록용 검증이기 때문에 app/Http/Requests/의 이름을 지었다.
    (이번에는 SPA용 인증 시스템의 인증도 자체적으로 업데이트되었습니다. 다시 쓸 필요가 없을 것 같습니다. 어차피 연습했으니까 그만둬요!)
    상기 명령을 통해 RegisterRequest.php의 부하들 사이에서 파일을 만들다RegisterRequest.php.

    창 편집 요청


    창설된 rules()는 다음과 같다!
    app/Http/Requests/RegisterRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    use Illuminate\Contracts\Validation\Validator;
    use Illuminate\Http\Exceptions\HttpResponseException;
    
    class RegisterRequest 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 [
                'name' => 'required|string|max:255',
                'email' => 'required|email|max:255|unique:users',
                'password' => 'required|min:8|confirmed',
            ];
        }
    
        public function messages()
        {
            return [
                'name.required' => 'ユーザー名を入力してください',
                'name.string' => '正しい形式で入力してください',
                'name.max' => '文字数をオーバーしています。',
                'email.required' => 'メールアドレスを入力してください。',
                'email.email' => '正しい形式でメールアドレスを入力してください',
                'email.max' => '文字数をオーバーしています。',
                'email.unique' => '登録済みのユーザーです',
                'password.required' => 'パスワードを入力してください',
                'password.min' => 'パスワードは8文字以上で入力してください。',
                'password.confirmed' => 'パスワードが一致しません。',
            ];
        }
    
        /**
         * [override] バリデーション失敗時ハンドリング
         *
         * @param Validator $validator
         * @throw HttpResponseException
         * @see FormRequest::failedValidation()
         */
        protected function failedValidation(Validator $validator)
        {
            $response['status']  = 422;
            $response['statusText'] = 'Failed validation.';
            $response['errors']  = $validator->errors();
            throw new HttpResponseException(
                response()->json($response, 200)
            );
        }
    }
    
    name = 'name' 방법에 검증 규칙을 기재한다.
    'name' => 'required|string|max:255',
    
    예를 들어post「入力必須」「文字列型」「最大文字数255」 요소에 대한 응용messages()에 대한 검증.'required|string|max:255' 방법에는 오류를 알릴 때의 정보가 기재되어 있다.
    'name.required' => 'ユーザー名を入力してください',
    'name.string' => '正しい形式で入力してください',
    'name.max' => '文字数をオーバーしています。',
    
    failedValidation()의 각 규칙에 대해 오류가 발생했을 때의 정보를 설정하는 인상을 준다.
    이번에는 SPA로 비동기 통신을 해야 하기 때문에 RegisterRequestTest.php 방법으로 검증 오류가 발생했을 때의 처리를 다시 쓴다.
    프론트 데스크에서
    javascript
    
    response(任意の変数名).data.errors
    
    대화 상자에서 오류 메시지를 추출합니다.
    スクリーンショット 2020-11-01 23.36.34.png

    창 요청 테스트 파일 만들기


    $ php artisan make:test RegisterRequestTest
    
    위 명령을 사용하여 생성tests/Feature합니다.
    기본적으로 tests/Unit 아래에 생성된 요청 테스트는 단원 테스트 처리로 Requests 아래에 Requests 디렉터리를 생성합니다.그리고 RegisterRequestTest.php 아래로 이동tests/Unit/Requests/RegisterRequestTest.php.dataUserRegistration()

    테스트 코드 편집


    테스트 코드를 편집하면 다음과 같습니다.
    tests/Unit/Requests/RegisterRequestTest.php
    <?php
    
    namespace Tests\Unit\Requests;
    
    use Illuminate\Support\Facades\Validator;
    use App\Http\Requests\RegisterRequest;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Tests\TestCase;
    
    
    class RegisterRequestTest extends TestCase
    {
        use RefreshDatabase;
    
        /**
         * カスタムリクエストのバリデーションテスト
         *
         * @param array 項目名の配列
         * @param array 値の配列
         * @param boolean 期待値(true:バリデーションOK、false:バリデーションNG)
         * @dataProvider dataUserRegistration
         */
        public function testUserRegistration(array $keys, array $values, bool $expect)
        {
            //入力項目の配列($keys)と値の配列($values)から、連想配列を生成する
            $dataList = array_combine($keys, $values);
    
            $request = new RegisterRequest();
            //フォームリクエストで定義したルールを取得
            $rules = $request->rules();
            //Validatorファサードでバリデーターのインスタンスを取得、その際に入力情報とバリデーションルールを引数で渡す
            $validator = Validator::make($dataList, $rules);
            //入力情報がバリデーショルールを満たしている場合はtrue、満たしていな場合はfalseが返る
            $result = $validator->passes();
            //期待値($expect)と結果($result)を比較
            $this->assertEquals($expect, $result);
        }
    
        public function dataUserRegistration()
        {
            return [
                'OK' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', '[email protected]', 'password', 'password'],
                    true
                ],
                '名前必須エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    [null, '[email protected]', 'password', 'password'],
                    false
                ],
                '名前形式エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    [1, '[email protected]', 'password', 'password'],
                    false
                ],
                '名前最大文字数エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    [str_repeat('a', 256), '[email protected]', 'password', 'password'],
                    false
                ],
                'OK' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    [str_repeat('a', 255), '[email protected]', 'password', 'password'],
                    true
                ],
                'email必須エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', null, 'password', 'password'],
                    false
                ],
                'email形式エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', 'test@example.', 'password', 'password'],
                    false
                ],
                'email最大文字数エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', str_repeat('a', 255) . '@example.com', 'password', 'password'],
                    false
                ],
                'emailユニークエラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', $this->user->email, 'password', 'password'],
                    false
                ],
                'password必須エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', '[email protected]', '', ''],
                    false
                ],
                'password最小文字数エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', '[email protected]', 'pass', 'pass'],
                    false
                ],
                'password一致エラー' => [
                    ['name', 'email', 'password', 'password_confirmation'],
                    ['testuser', '[email protected]', 'password', 'password1'],
                    false
                ],
            ];
        }
    }
    
    testUserRegistration() 방법에 테스트 용례를 쓰고 각 용례key 방법에 대해 실제 테스트를 실시한다.
    테스트 용례의 구체적인 예를 보겠습니다.
    public function dataUserRegistration()
        {
            return [
                'OK' => [
                    ['name', 'email', 'password', 'password_confirmation'], //第一引数
                    ['testuser', '[email protected]', 'password', 'password'], //第二引数
                    true  //第三引数
                ],
         }
    
    발리데이value가 저장된 수조를 제1파라미터로, 발리데이testUserRegistration()가 저장된 수조를 제2파라미터로, 발리데이 결과의 기대치의 진위치를 제3파라미터로 설정하여 testUserRegistration()에 전달한다.
    테스트 방법testUserRegistration()은 상기 3개 파라미터를 받아들인다.
    
        /**
         * カスタムリクエストのバリデーションテスト
         *
         * @param array 項目名の配列
         * @param array 値の配列
         * @param boolean 期待値(true:バリデーションOK、false:バリデーションNG)
         * @dataProvider dataUserRegistration
         */
        public function testUserRegistration(array $keys, array $values, bool $expect)
        {
         //
        }
    
    unique 방법 내의 각 처리 내용은 주석과 같다.스케줄러:너무 지저분해서 못 맞춰!

    주의 사항


    use Refresh Database 규칙은 Register Request입니다.php 필요


    첫 번째 주의점은 폼 요청email의 검증 규칙입니다
    app/Http/Requests/RegisterRequest.php
    public function rules()
    {
         return [
             'name' => 'required|string|max:255',
             'email' => 'required|email|max:255|unique:users',
             'password' => 'required|min:8|confirmed',
         ];
    }
    
    테스트 시 이 글[Laavel] DB를 PHPUnit 테스트용으로 설정하여 기본 DB를 더럽히지 않음을 참고하여 SQLite의 메모리 액세스 기능을 사용하면 실제 데이터베이스를 오염시키지 않고 테스트에서 데이터베이스와 통신하지 않지만 이번unique의 규칙이 있어 데이터베이스와 통신한다.
    'email' => 'required|email|max:255|unique:users',
    
    use RefreshDatabase가 없으면 다음과 같은 오류가 발생합니다.
    SQLSTATE[HY000]: General error: 1 no such table: users (SQL: select count(*) as aggregate from "users" where "email" = [email protected])
    
    Illuminate\Foundation\Testing\RefreshDatabase, 클래스에 기재use를 통해 테스트 방법이 실행되기 전에
    $ php artisan migrate:fresh
    
    집행.
    tests/Requests/RegisterRequestTest.php
    <?php
    
    namespace Tests\Requests;
    
    use Illuminate\Support\Facades\Validator;
    use App\Http\Requests\RegisterRequest;
    use Illuminate\Foundation\Testing\RefreshDatabase; //←これが必要
    use Tests\TestCase;
    
    
    class RegisterRequestTest extends TestCase
    {
        use RefreshDatabase;  //←これが必要
    

    명명 규칙


    두 번째 주의점은 코드 테스트 방법의 명칭 규칙이다.
    테스트 방법은 반드시 접두사에 "use RefreshDatabase;"을 붙여야 한다(그렇지 않으면 오류가 발생할 수 있다).
    또한 공급자 방법test***은 테스트 방법의 doc 주석dataUserRegistration()에 제시된 형식으로 지정해야 한다(지정하지 않으면 오류가 발생할 수 있다).
    상세한 상황은 여기에 있다
    데이터 공급자
    tests/Requests/RegisterRequestTest.php
        /**
         (中略)
         * @dataProvider dataUserRegistration //←これです
         */
        public function testUserRegistration(array $keys, array $values, bool $expect)
        {
    

    (참조) phpunit.xml 편집


    이번에@dataProviderRegisterRequestTest.php의 부하에 배치되었기 때문에 문제가 없다. 예를 들어tests/Unit/Requests 부하 배치tests/Requests의 경우 RegisterRequestTest.php의 부하가 테스트 코드라는 것을 깨닫게 하기 위해 편집tests/Requests이 필요하다.
    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 파일 자체는 기본적으로 Laavel의 프로젝트에 준비됩니다.
    상기 샘플 코드에 추가된 것은 다음과 같은 부분이다.
    <testsuite name="Unit Tests">
        <directory suffix="Test.php">./tests/Requests</directory>
    </testsuite>
    
    phpunit.xml 부하로 식별된 것은 테스트 코드다.

    코드 실행 테스트


    $ php artisan test
    
    ./tests/RequestsLaavel7 시스템부터 사용하는 방법인 것 같아요.
    $ vendor/bin/phpunit
    
    로 대체할 수 있습니다.

    기타


    각양각색의 테스트 용례를 준비하는 것은 매우 어려운데, 또 다른 좋은 방법이 있습니까?있으면 알려주세요!
    이번에는 $ php artisan test·name·email 세 가지 모델이지만 실제로도 더 많은 모델이 있어 지수가 늘어난다.


    처음엔 살짝 말했는데 지금은'모두의 조합 취합 사이트'를 만들고 있다.
    나는 프로그래밍 학자를 처음 했을 때'다른 사람이 어떤 조합을 만들었는지 알고 싶었지만 그 정보를 거의 찾지 못했다(나는 아직이라고 생각한다).
    "그럼 나 혼자 할게!"자신의 기술 성과와 함께 React×Laavel을 사용하여 SPA로 제작.
    완성까지 한두 달 남았지만 열심히 보내겠습니다!
    '여러분의 조합 모음 사이트'제작 일기입니다.
    [제0회]'여러분의 조합 모음 사이트'만들기~ 선언편~
    [제1회]'여러분의 조합 모음 사이트'만들기~ 손편~
    [제2회]'여러분의 조합 집합 사이트'만들기~스파 인증의 사투편~

    좋은 웹페이지 즐겨찾기