Setup Unit Test with PHP Laravel in windows

# Outline 
前回、Laravel + MariaDB + IIS といろんな環境を構築して、phpunitを使う環境のドキュメントを作成した。
今回はシンプルに、phpunitを学習するための最低限の環境を構築、かつサンプルコードで１つ書いてみるところまでをドキュメントとして残す


#  PHP

## install PHP

https://www.php.net/

php windows versionのzipをダウンロードする。
今回、Non Thread Safe versionを使う。

Thread Safeに関する記事は、以下参照。使用環境によって異なる。

https://techplay.jp/column/504

zipをdownload後、解凍し任意の場所に配置する。
今回、一般的に使われる、c:\phpに配置した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/5ffb719f-9d79-6ae4-9783-596109ab9090.png)

その後、phpのpathを設定する。
今回、 path = c:\php を追加した。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/3dda3b2a-e6c5-830b-7328-3734a1bfc1c2.png)

その後、任意のpathでphpコマンドを実行する

```
php -i
```

## setup php.ini

phpの設定ファイルを用意する。
defaultでは、2つのiniがtemplateとして用意されている
- php.ini-development  (開発環境用 - debug mode出力などが有効になっている)
- php.ini-production   (本番環境用）

今回、development用を使うため、php.ini-developmentをcopyしてphp.iniとして配置する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/49be807f-b6ff-af59-dece-9cbcc343064c.png)


## install xdebug

xdebugは、unittest coverageを出力してくれるextensionである。

https://xdebug.org/wizard

このサイトに準じてすすめると、以下のようにphp.iniの設定方法まで表示されるため、それに従いxdebugを有効にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/f6666714-b7df-d072-76a5-4396747fa5f0.png)


## install Composer

Composerとは、PHPと必要なライブラリの依存関係を管理する標準形式を提供するアプリケーションレベルのパッケージ管理システム
Laravelをinstallするときに使う
インストーラーをdownloadして、基本的にデフォルトでインストールを行えばよい

https://getcomposer.org/download/

尚、install中に以下のように警告が出るときがある。
その時は、php extensionの設定が足らないため、都度php.iniを修正する必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/e9004b4f-fdb8-8350-39a4-38b9ff25a244.png)


install後、command promptを立ち上げて、composerを起動する

```
composer
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/5c4715c6-0d86-9377-7b28-aad7db072b2d.png)

## install Laravel

composerを使用して、laravelをinstallする

```
composer global require "laravel/installer"
```

その後、laravelコマンドが有効か試す

```
laravel
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/fc88c001-c1b2-5a83-a955-1a29f27fe592.png)


## install phpunit

unit testである、phpunitをinstallする

```
composer require --dev phpunit/php-code-coverage
```


# Laravel Project

## create Laravel Project

Laravel project を新規作成する

```
laravel new ut_sample
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/8d9a8689-ec45-cdd4-9454-95b5d010f148.png)


実行後、以下のようにlaravel projectのtemplateが作成される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/cea8d694-6dca-4270-c781-0bfe33fd3fb0.png)

## update composer.json

unit-test coverageの結果をhtmlで出力できるようにする。
そのため、作成したprojectのcomposer.jsonのscriptsの中で以下を追加する

```
        "test:coverage-html": [
            "@putenv XDEBUG_MODE=coverage",
            "./vendor/bin/phpunit --color=always --coverage-html=\"storage/logs/code-coverage\""
        ]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/8ea9a48f-0302-3827-7f2e-70994473ca03.png)


設定後、対象project配下で以下のコマンドを実行する


```
composer test:coverage-html
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/0166fa6b-ca29-4494-8f3f-374d58e91e4f.png)

その後、storage/logs/code-coverage　にcoverageのhtmlが作成される。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/dd90aed0-15d8-f43e-376e-604de72ba9c1.png)


## feature / unit test

laravelのfeature testと unit testは以下folderで作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/fc8c8402-9051-930a-d296-75847e1942b8.png)


project配下で以下コマンドを実行することで、2つのtypeのtestを行う。

```
php artisan test
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/94b6dc6f-b513-2a81-eba4-d0cbaee1adf4.png)


## 実際に簡単なclassのunit testを書いてみる

app以下に、SampleUser.phpを作成する。
このclassはpasswordで以下条件を満たすかをしらべるmethodを持つ。
- Password length is 8 ~ 16
- Available word is alphabet & number
- 1 capital letter , 1 small letter ,  1 number should be included



SampleUser.php
```
<?php

namespace App;

class SampleUser
{
	protected $password;
	// ** setter **/
	public function setPassword($pwd)
	{
		$this->password = $pwd;
	}

    /** validate password **/
    public function validatePassword()
    {
    	$result = true;
    	
    	// validate length
    	$length = mb_strlen($this->password);
    	if ($length < 8 || $length > 16) {
    		$result = false;
    	}

    	// character accept a-z,A-Z,0-9
    	if (preg_match("/[^a-zA-Z0-9]/",$this->password) == true) {
    		$result = false;
    	}
    	if (preg_match("/[a-z]/",$this->password) == false) {
    		$result = false;
    	}
    	if (preg_match("/[A-Z]/",$this->password) == false) {
    		$result = false;
    	}
    	if (preg_match("/[0-9]/",$this->password) == false) {
    		$result = false;
    	}


    	return $result;
    }


}
```

次に、unit test codeを作成する
tests\Unit 配下に作成する。
まず、長さのtest codeを一つ書いてみる

UserTest.php
```
<?php

namespace Tests\Unit;

use Tests\TestCase;
use App\SampleUser;

class UserTest extends TestCase
{

    /** @test password length **/
    public function return_validate_password_lenght(){

        $user = new SampleUser();
        
        // length 7 : false
        $user->setPassword('1234567');

        $result = $user->validatePassword();
        $this->assertFalse( $result);
        
    }

}
```

そのうえで、テストを実行する

```
php artisan test
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/5615c0c8-9fa3-0eb5-5df3-405658c4e0bb.png)

このように、1 test codeが正しく通ることを確認。

次にcoverageを確認する

```
composer test:coverage-html
```

htmlを開いてみると、今回の対象Class SampleUser.php のcoverageが50%を満たしていることがわかる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/c9a8e181-7088-5632-3394-89746c1c0d6c.png)



今度は、100%になるように、最低限のtest codeを作成する

```
<?php

namespace Tests\Unit;

use Tests\TestCase;
use App\SampleUser;

class UserTest extends TestCase
{

    /** @test password length **/
    public function return_validate_password_lenght(){

        $user = new SampleUser();
        
        // length 7 : false
        $user->setPassword('1234567');

        $result = $user->validatePassword();
        $this->assertFalse( $result);

    }
    
    /** @test password charactor **/
    public function return_validate_password_charactor(){

        $user = new SampleUser();
        

        // charactor
        $user->setPassword('aA');

        $result = $user->validatePassword();
        $this->assertFalse( $result);

        // non allow  charactor 
        $user->setPassword('@');

        $result = $user->validatePassword();
        $this->assertFalse( $result);

    }

}
```

このテストコードによる結果、100% coverageを見たいしていることが確認できる。
ただ、これは phpunit が C0 coverage のため、上記テストコードで満たしてしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/a2e3a4dc-8347-d9bc-5b35-4740c02b2806.png)