PHPUnit用テストDB設定方法

<h1>PHP Unitでテストを行うためのテスト用DBを導入するまで</h1>
Laravel開発にてテスト行う際は、PHP UnitというPHP用のユニットテストプログラムが標準で組み込まれており、テストコードを記述するとテストを実行してくれるとのこと。
早速PHP Unitにてテスト実行するためのテスト用DBを作成・設定したのでまとめます。

<h2>手順概要</h2>
1. MySQLにてテスト用DBを作成
1. config/database.php変更
1. .env.testing作成
1. phpunit.xml変更


<h2>手順詳細</h2>
<h3>MySQLにてテスト用DB作成</h3>
mysqlに接続し、以下コマンドでテスト用DBを作成

```sql:
create database TestDababase;
```

<h3>config/database.php変更</h3>
laravelプロジェクト内のconfigフォルダ下にあるdatabase.phpに使用するDB定義を追加します。
connections配列の中にあるmysqlの内容を丸々コピーして複製。
キーの名称をmysqlからテスト用のDB定義名称に変更。

```php:database.php

// その他設定項目省略
'connections' => [
　　　　　　　　　　// ↓mysqlからテスト用名称に変更
    'test_laravel' => [
        'driver' => 'mysql',
        'url' => env('DATABASE_URL'),
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => null,
        'options' => extension_loaded('pdo_mysql') ? array_filter([
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        ]) : [],
    ],
],
```

<h3>.env.testingを作成</h3>
Laravelプロジェクトフォルダ直下にある「.env」をコピーし、「.env.testing」に変更。
変更箇所は以下の4箇所です。

「APP_ENV」 :任意の名称
「DB_CONNECTION」 :database.php内に定義したテスト用DB定義名称
「DB_DATABASE」 ：１つ目の手順で作成したTestDBの名称を入力。
「APP_Key」 ：次手順のコマンドで自動で入力されるため空欄にしておきます。

```:.env.testing
APP_ENV= test_laravel
APP_KEY= （空に設定）
DB_DATABASE= test_laravel
DB_DATABASE= TestDatabase
```

config内容を変更しているので、一旦configキャッシュをクリア

```bash:terminal
php artisan config:clear
```

test用App_Keyを作成するため以下のコマンドでキーを作成
このコマンドで.env.testing内のAPP_KEYに値が入力されます。

```bash:terminal
php artisan key:generate --env=testing
```

上記手順完了したらテスト用DBをmigrate。

```bash:terminal
php artisan migrate --env=testing
```

これでTest用に作成したDB内にテーブルが作成されます。

<h3>phpunit.xmlを変更</h3>
最後にプロジェクト直下にある「phpunit.xml」の内容を変更します。
「DB_CONNECTION」の値に、database.php内に定義したテスト用DB定義名称を記入。

```:phpunit.xml
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="MAIL_DRIVER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="test_laravel"/>
```

ここまでできたらphpunitを動かし、正常にテストが実行されていれば設定完了です。


<h2>備考</h2>
.envと.env.testingの切り替えの仕組みが気になったので調べてみたところ
phpunit.xmlの内容のAPP_ENVのvalueの内容を読み取り、「.env.{{APP_ENV}}」のファイルを環境変数設定ファイルとして読み込みに行くとのこと。

```:phpunit.xml
<server name="APP_ENV" value="testing"/>
```

試しに以下コードをテストコード内に記述してキーの名称を色々変えてみると設定ファイルとして.env.testingを読み込んでいることがわかります。

```php:testExample.php
dd(env('APP_ENV'), env('DB_HOST'));
```

Laravelは設定ファイルをキャッシュしているため、DBを扱うテストコードを実行する前に php artisan config:clear を実行した方がいいとのこと。
設定変えてもddで反映されない場合はconfigをクリアするとうまく行くかと思います。

### dockerでphpunitを使用する場合
※ dockerでphpunit実行する場合はserverタグをenvタグに書き換える必要がある

```:phpunit.xml
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="MAIL_DRIVER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="test_laravel"/>
```