Laravelアプリで開発テスト2 - データベースのテスト編（前編） -

[前回](https://qiita.com/wantonbe/items/9a7e13ab362457bdbed1)は超準備編としてLaravelで開発テストをする環境づくりをしました。今回はデータベースを使ったテストについて書いていきます。環境の前提とかは前回の記事を参照ください。
（ちょっと長くなっちゃったので環境構築をする前編と実際のテストを書いていく後編で分割します）

# 環境準備

## 普通にmigrationをする

Laravelは`migration`の機構があるので`migration`ファイルを活用していきます。実際にscaffoldしてみましょう。scaffoldは`artisan`コマンドでできます。今回はモデルのファイルも一緒につくります。
`make:model`したときに`--migration`オプションをつけるとまとめてつくれるので便利です。（https://qiita.com/kobiyama/items/0d34fc07796d9a3c681d）

```
$ php artisan make:model Models/Eloquent/Message --migration
Model created successfully.
Created Migration: 2018_11_26_003309_create_messages_table
```

ファイルができたら`.env`ファイルにデータベースへの接続情報を書きいて実際にmigrationしてみましょう。データベースは`docker`などで適当につくってください。

**dockerで mysqlを立てる**

```
$ docker run -d -v /var/lib/mysql --name storage busybox true
$ docker run -d --name mysql -e MYSQL_ROOT_PASSWORD={{ password }} -p 3306:3306 --volumes-from storage mysql:5.7
$ docker exec -it mysql mysqladmin create laravel -u root -p
Enter password:
```

**.envファイル**（データベースの設定のみ抜粋）

```..env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD={{ password }}
```

**migrationを実行する**

```
$ php artisan migrate
Migration table created successfully.
Migrating: 2018_11_26_003309_create_messages_table
Migrated:  2018_11_26_003309_create_messages_table
```

migrationができたことを確認しました。

## 開発テスト用のデータベース環境を作る

### データベースをつくる

さてここから開発テストをする環境を作っていきます。データベースを使ったテストをする時は開発の環境と別のデータベースを使います。テストをするときは初期状態にリセットをしておかないと状況に依存してしまってテスト結果が安定しないからです。テストの原則としていつやっても同じ結果になる、というのは重要ですので開発中とは別のデータベースを用意しましょう。

```
$ docker exec -it mysql mysqladmin create laravel_test -u root -p
Enter password:
```

### .envファイルをつくる

データベースを作ったらテスト用の.envファイルをつくります。Laravelは環境変数で読み込む.envファイルを切り替えられるのでテスト用の.envファイルを作りましょう。以下に差分を載せます。

```..env.testing
APP_ENV=testing

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_test
DB_USERNAME=root
DB_PASSWORD={{ password }}
```

### テスト用のデータベースにmigrationする

テスト用のデータベースとenvファイルができたのでテスト用環境にmigrationをかけます。`env`オプションで環境変数を渡すことで読み込むenvファイルを変更することができます。

```
$ php artisan migrate --env=testing
Migration table created successfully.
Migrating: 2018_11_26_003309_create_messages_table
Migrated:  2018_11_26_003309_create_messages_table
```

### テスト用のbootstrap.phpをつくる

テストの準備としてもう1つあります。テストを実行するときはテスト用の.envファイルを読み込むようにします。最近のphpアプリはbootstrap.phpというファイルでアプリの初期処理をおこなうのでこちらもテスト用に用意します。

```tests/bootstrap.php
<?php

require_once __DIR__ . '/../vendor/autoload.php';

$dotenv = new Dotenv\Dotenv(dirname(__DIR__), '.env.testing');
$dotenv->load();
```

やっていることは`vendor/autoload.php`をloadしてテスト用の`.env`ファイルを読み込みです。たったこれだけですがこの設定をしておくことで開発環境をつくるのと同じようにテスト環境もつくっていけるようになります。
データベースの設定とかは`phpunit.xml`に書くやりかたもあるかと思いますが、それだとデータベース名・ユーザー名が固定になるしなによりgitのログに重要な情報が残ってしまうのでテスト用の`.env`ファイルを用意してそれを読み込むという方法をとりましょう。

### phpunit.xmlでテスト用のbootstrap.phpを読み込む

最後に`phpunit.xml`でテスト用`bootstrap.php`を参照するようにします。`bootstrap=`のところにテスト用につくった`bootstrap.php`を設定します。`tests/bootstrap.php`で最初に読み込んだ`vendor/autoload.php`はここでデフォルトで読んでいたので記述しています。

```diff:phpunit.xml
 <?xml version="1.0" encoding="UTF-8"?>
 <phpunit backupGlobals="false"
          backupStaticAttributes="false"
-         bootstrap="vendor/autoload.php"
+         bootstrap="tests/bootstrap.php"
          colors="true"
          convertErrorsToExceptions="true"
          convertNoticesToExceptions="true"
```

これでテストをする準備ができあがりました。一応この状態でテストを実行して設定が間違っていないことを確認します。

```
$ ./vendor/bin/phpunit 
PHPUnit 6.5.13 by Sebastian Bergmann and contributors.

.                                                                  2 / 2 (100%)

Time: 325 ms, Memory: 14.00MB

OK (2 tests, 2 assertions)
```

完璧ですね！

# まとめ

- テスト用のデータベース環境、.envファイルは別に用意しよう
- テスト用の.envファイルを読み込むようにbootstrap.phpを使う

実際にどういう風にテストを書くかは後半に続きます。