[{"data":1,"prerenderedAt":564},["ShallowReactive",2],{"article-laravel-validation-unit-test":3},{"id":4,"title":5,"body":6,"category":551,"createdAt":553,"description":5,"extension":554,"index":555,"meta":556,"navigation":56,"path":557,"publish":56,"seo":558,"series":555,"seriesTitle":555,"stem":559,"tag":560,"thumbnail":562,"updatedAt":555,"__hash__":563},"articles\u002Farticles\u002Flaravel-validation-unit-test.md","Laravelでカスタムバリデーションのユニットテストをする方法",{"type":7,"value":8,"toc":544},"minimark",[9,18,21,25,28,121,124,131,322,325,328,332,335,355,365,368,371,426,429,482,503,511,514,537,540],[10,11,12,13,17],"p",{},"Laravelでは",[14,15,16],"code",{},"Illuminate\\Contracts\\Validation\\Rule","を継承したクラスを用いてカスタムなバリデーションを作成することができます。そしてサービスプロバイダに登録することで、FormRequestで文字列で指定することでリクエストのバリデーションを拡張できます。",[10,19,20],{},"ただしこの様な独自コードはきちんとユニットテストをすることが大切です。Laravelではこのカスタムバリデーションを簡単にユニットテストをすることができます。",[22,23,24],"h2",{"id":24},"サンプルのバリデーション",[10,26,27],{},"とりあえず以下の様な郵便番号のバリデーションを作成したとします。７桁のハイフンなしの数字が郵便番号の形式とします。",[29,30,35],"pre",{"className":31,"code":32,"language":33,"meta":34,"style":34},"language-php shiki shiki-themes material-theme-ocean","namespace App\\Rules;\nuse Illuminate\\Contracts\\Validation\\Rule;\n\nclass Zipcode implements Rule{\n\n    public function passes($attribute, $value)\n    {\n        return preg_match('\u002F^[0-9]{3}-?[0-9]{4}$\u002F', $value);\n    }\n\n    public function message(){\n        return '郵便番号は7桁の半角数字で入力してください。';\n    }\n}\n","php","",[14,36,37,45,51,58,64,69,75,81,87,93,98,104,110,115],{"__ignoreMap":34},[38,39,42],"span",{"class":40,"line":41},"line",1,[38,43,44],{},"namespace App\\Rules;\n",[38,46,48],{"class":40,"line":47},2,[38,49,50],{},"use Illuminate\\Contracts\\Validation\\Rule;\n",[38,52,54],{"class":40,"line":53},3,[38,55,57],{"emptyLinePlaceholder":56},true,"\n",[38,59,61],{"class":40,"line":60},4,[38,62,63],{},"class Zipcode implements Rule{\n",[38,65,67],{"class":40,"line":66},5,[38,68,57],{"emptyLinePlaceholder":56},[38,70,72],{"class":40,"line":71},6,[38,73,74],{},"    public function passes($attribute, $value)\n",[38,76,78],{"class":40,"line":77},7,[38,79,80],{},"    {\n",[38,82,84],{"class":40,"line":83},8,[38,85,86],{},"        return preg_match('\u002F^[0-9]{3}-?[0-9]{4}$\u002F', $value);\n",[38,88,90],{"class":40,"line":89},9,[38,91,92],{},"    }\n",[38,94,96],{"class":40,"line":95},10,[38,97,57],{"emptyLinePlaceholder":56},[38,99,101],{"class":40,"line":100},11,[38,102,103],{},"    public function message(){\n",[38,105,107],{"class":40,"line":106},12,[38,108,109],{},"        return '郵便番号は7桁の半角数字で入力してください。';\n",[38,111,113],{"class":40,"line":112},13,[38,114,92],{},[38,116,118],{"class":40,"line":117},14,[38,119,120],{},"}\n",[22,122,123],{"id":123},"ユニットテストファイルを作成",[10,125,126,127,130],{},"ひとまず ",[14,128,129],{},"tests\u002FUnit\u002FRules.php"," というものを作成します。",[29,132,135],{"className":31,"code":133,"filename":134,"language":33,"meta":34,"style":34},"namespace Tests\\Unit;\n\nuse App\\Rules\\Zipcode;\nuse Illuminate\\Foundation\\Testing\\TestCase;\nuse Tests\\CreatesApplication;\nuse Illuminate\\Support\\Facades\\Validator;\nuse \\Illuminate\\Validation\\ValidationException;\n\nclass Rules extends TestCase{\n    use CreatesApplication;\n\n    public function test_zipcode_validation(){\n        $tests = [\n            '1234567'=>true,\n            '0012344'=>true,\n            '0012340'=>true,\n            '12345678'=>false,\n            '123456'=>false,\n            '1234 56'=>false,\n            '1234a56'=>false,\n            '1234_56'=>false,\n        ];\n        foreach($tests as $key => $condition){\n            try{\n                Validator::make(['test'=>$key],[\n                    'test'=> new Zipcode()\n                ])->validate();\n                $this->assertTrue($condition===true);\n            }catch(ValidationException $e){\n                $this->assertFalse($condition);\n            }\n        }\n    }\n}\n","Rules.php",[14,136,137,142,146,151,156,161,166,171,175,180,185,189,194,199,204,210,216,222,228,234,240,246,252,258,264,270,276,282,288,294,300,306,312,317],{"__ignoreMap":34},[38,138,139],{"class":40,"line":41},[38,140,141],{},"namespace Tests\\Unit;\n",[38,143,144],{"class":40,"line":47},[38,145,57],{"emptyLinePlaceholder":56},[38,147,148],{"class":40,"line":53},[38,149,150],{},"use App\\Rules\\Zipcode;\n",[38,152,153],{"class":40,"line":60},[38,154,155],{},"use Illuminate\\Foundation\\Testing\\TestCase;\n",[38,157,158],{"class":40,"line":66},[38,159,160],{},"use Tests\\CreatesApplication;\n",[38,162,163],{"class":40,"line":71},[38,164,165],{},"use Illuminate\\Support\\Facades\\Validator;\n",[38,167,168],{"class":40,"line":77},[38,169,170],{},"use \\Illuminate\\Validation\\ValidationException;\n",[38,172,173],{"class":40,"line":83},[38,174,57],{"emptyLinePlaceholder":56},[38,176,177],{"class":40,"line":89},[38,178,179],{},"class Rules extends TestCase{\n",[38,181,182],{"class":40,"line":95},[38,183,184],{},"    use CreatesApplication;\n",[38,186,187],{"class":40,"line":100},[38,188,57],{"emptyLinePlaceholder":56},[38,190,191],{"class":40,"line":106},[38,192,193],{},"    public function test_zipcode_validation(){\n",[38,195,196],{"class":40,"line":112},[38,197,198],{},"        $tests = [\n",[38,200,201],{"class":40,"line":117},[38,202,203],{},"            '1234567'=>true,\n",[38,205,207],{"class":40,"line":206},15,[38,208,209],{},"            '0012344'=>true,\n",[38,211,213],{"class":40,"line":212},16,[38,214,215],{},"            '0012340'=>true,\n",[38,217,219],{"class":40,"line":218},17,[38,220,221],{},"            '12345678'=>false,\n",[38,223,225],{"class":40,"line":224},18,[38,226,227],{},"            '123456'=>false,\n",[38,229,231],{"class":40,"line":230},19,[38,232,233],{},"            '1234 56'=>false,\n",[38,235,237],{"class":40,"line":236},20,[38,238,239],{},"            '1234a56'=>false,\n",[38,241,243],{"class":40,"line":242},21,[38,244,245],{},"            '1234_56'=>false,\n",[38,247,249],{"class":40,"line":248},22,[38,250,251],{},"        ];\n",[38,253,255],{"class":40,"line":254},23,[38,256,257],{},"        foreach($tests as $key => $condition){\n",[38,259,261],{"class":40,"line":260},24,[38,262,263],{},"            try{\n",[38,265,267],{"class":40,"line":266},25,[38,268,269],{},"                Validator::make(['test'=>$key],[\n",[38,271,273],{"class":40,"line":272},26,[38,274,275],{},"                    'test'=> new Zipcode()\n",[38,277,279],{"class":40,"line":278},27,[38,280,281],{},"                ])->validate();\n",[38,283,285],{"class":40,"line":284},28,[38,286,287],{},"                $this->assertTrue($condition===true);\n",[38,289,291],{"class":40,"line":290},29,[38,292,293],{},"            }catch(ValidationException $e){\n",[38,295,297],{"class":40,"line":296},30,[38,298,299],{},"                $this->assertFalse($condition);\n",[38,301,303],{"class":40,"line":302},31,[38,304,305],{},"            }\n",[38,307,309],{"class":40,"line":308},32,[38,310,311],{},"        }\n",[38,313,315],{"class":40,"line":314},33,[38,316,92],{},[38,318,320],{"class":40,"line":319},34,[38,321,120],{},[10,323,324],{},"バリデーションテストでは正しい形式は正しいと判断（ポジティブテスト）し、間違っているものは間違っていると判断（ネガティブテスト）できているかをテストします。\nもしも正しいのに間違っていると判断したり、間違っているのに正しいとなったらテストが失敗する様になっています。",[10,326,327],{},"ここでバリデーションテストの詳細を解説します。",[329,330,331],"h3",{"id":331},"バリデーションのインスタンスを作成",[10,333,334],{},"最初にテストしたいバリデーションのインスタンス、そしてバリデーターインスタンスを作成します。",[29,336,338],{"className":31,"code":337,"language":33,"meta":34,"style":34},"Validator::make(['test'=>$key],[\n    'test'=> new Zipcode()\n])->validate();\n",[14,339,340,345,350],{"__ignoreMap":34},[38,341,342],{"class":40,"line":41},[38,343,344],{},"Validator::make(['test'=>$key],[\n",[38,346,347],{"class":40,"line":47},[38,348,349],{},"    'test'=> new Zipcode()\n",[38,351,352],{"class":40,"line":53},[38,353,354],{},"])->validate();\n",[10,356,357,360,361,364],{},[14,358,359],{},"Validator","では",[14,362,363],{},"make()","を使用して第一引数に、バリデーションをする値とキーを設定します。第二引数にはバリデーションのキーとバリデーションインスタンスを指定します。",[329,366,367],{"id":367},"いろんなパターンをテストする",[10,369,370],{},"いろいろなパターンをテストするため以下の様に配列でテストパターンと予期する正誤を設定します。Trueはバリデーション通過で、Falseはバリデーション違反（間違った形式）であることを示します。",[29,372,374],{"className":31,"code":373,"language":33,"meta":34,"style":34},"$tests = [\n    '1234567'=>true,\n    '0012344'=>true,\n    '0012340'=>true,\n    '12345678'=>false,\n    '123456'=>false,\n    '1234 56'=>false,\n    '1234a56'=>false,\n    '1234_56'=>false,\n];\n",[14,375,376,381,386,391,396,401,406,411,416,421],{"__ignoreMap":34},[38,377,378],{"class":40,"line":41},[38,379,380],{},"$tests = [\n",[38,382,383],{"class":40,"line":47},[38,384,385],{},"    '1234567'=>true,\n",[38,387,388],{"class":40,"line":53},[38,389,390],{},"    '0012344'=>true,\n",[38,392,393],{"class":40,"line":60},[38,394,395],{},"    '0012340'=>true,\n",[38,397,398],{"class":40,"line":66},[38,399,400],{},"    '12345678'=>false,\n",[38,402,403],{"class":40,"line":71},[38,404,405],{},"    '123456'=>false,\n",[38,407,408],{"class":40,"line":77},[38,409,410],{},"    '1234 56'=>false,\n",[38,412,413],{"class":40,"line":83},[38,414,415],{},"    '1234a56'=>false,\n",[38,417,418],{"class":40,"line":89},[38,419,420],{},"    '1234_56'=>false,\n",[38,422,423],{"class":40,"line":95},[38,424,425],{},"];\n",[10,427,428],{},"そしてforeachでそれぞれチェックします。",[29,430,432],{"className":31,"code":431,"language":33,"meta":34,"style":34},"foreach($tests as $key => $condition){\n    try{\n        Validator::make(['test'=>$key],[\n            'test'=> new Zipcode()\n        ])->validate();\n        $this->assertTrue($condition===true);\n    }catch(ValidationException $e){\n        $this->assertFalse($condition);\n    }\n}\n",[14,433,434,439,444,449,454,459,464,469,474,478],{"__ignoreMap":34},[38,435,436],{"class":40,"line":41},[38,437,438],{},"foreach($tests as $key => $condition){\n",[38,440,441],{"class":40,"line":47},[38,442,443],{},"    try{\n",[38,445,446],{"class":40,"line":53},[38,447,448],{},"        Validator::make(['test'=>$key],[\n",[38,450,451],{"class":40,"line":60},[38,452,453],{},"            'test'=> new Zipcode()\n",[38,455,456],{"class":40,"line":66},[38,457,458],{},"        ])->validate();\n",[38,460,461],{"class":40,"line":71},[38,462,463],{},"        $this->assertTrue($condition===true);\n",[38,465,466],{"class":40,"line":77},[38,467,468],{},"    }catch(ValidationException $e){\n",[38,470,471],{"class":40,"line":83},[38,472,473],{},"        $this->assertFalse($condition);\n",[38,475,476],{"class":40,"line":89},[38,477,92],{},[38,479,480],{"class":40,"line":95},[38,481,120],{},[10,483,484,487,488,491,492,494,495,498,499,502],{},[14,485,486],{},"validate()","メソッドは失敗すると",[14,489,490],{},"ValidationException"," を投げます。そのため例外処理で",[14,493,490],{}," をキャッチします。正しい形式を正しいと判断できれば",[14,496,497],{},"$this->assertTrue($condition===true);","となり、まちがった形を間違っていると判断できればキャッチして",[14,500,501],{},"$this->assertFalse($condition);","でアサートされます。",[29,504,509],{"className":505,"code":507,"language":508},[506],"language-text","php artisan test \n","text",[14,510,507],{"__ignoreMap":34},[10,512,513],{},"にてテストを行い問題なければそのまま通過します。テストは以上の方法でいろんなパターンをテストできます。パターンは思いついたものを配列に書いてもいいですし、プログラム的に大量に配列を生成してもいいかもしれません。まとめると",[515,516,517,521,526],"ul",{},[518,519,520],"li",{},"バリデーションインスタンスを作成",[518,522,523,525],{},[14,524,490],{},"を用いて間違っている形を識別",[518,527,528,529,532,533,536],{},"バリデーション対象の値が正誤かどうかは",[14,530,531],{},"assertTrue","と",[14,534,535],{},"assertFalse","で正しく判断できているかをアサート",[10,538,539],{},"こんな感じです。私はこのテストで結構救われたので、バリデーションを作った時は必ずユニットテストをしましょう。",[541,542,543],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":34,"searchDepth":53,"depth":53,"links":545},[546,547],{"id":24,"depth":47,"text":24},{"id":123,"depth":47,"text":123,"children":548},[549,550],{"id":331,"depth":53,"text":331},{"id":367,"depth":53,"text":367},[552],"ministack","2022-03-25","md",null,{},"\u002Farticles\u002Flaravel-validation-unit-test",{"title":5,"description":5},"articles\u002Flaravel-validation-unit-test",[33,561],"laravel","_common\u002Flaravel.png","_6kCaD6uDnBdQkj-XY_8G39zixCeVekVE-xS127shV4",1780987143056]