ユニットテストを行うときは本番用のDBに影響がないように、
テスト用のDBやテスト用のデータを用意してテストをしたいと思います。
それをLaravelで行う方法をまとめてみました。
環境
CentOS7.0
nginx 1.10
MySQL 5.7
PHP7.1
Larabel 5.3
テスト用のデータを使う
今回はModelFactoryを使ってテスト用のデータを作って使ってみました。
手順1:database/factories/ModelFactory.php
テスト用データを2件作る。
(今回は説明のため2件作ったが1件〜で作って大丈夫。)
$factory->defineAs(App\Post::class, 'first', function (Faker\Generator $faker) {
return [
'title' => 'テストタイトル1',
'content' => 'テスト本文1',
'created_at' => "2017-02-02 10:10:53",
];
});
$factory->defineAs(App\Post::class, 'second', function (Faker\Generator $faker) {
return [
'title' => 'テストタイトル2',
'content' => 'テスト本文2',
'created_at' => "2017-02-03 10:10:53",
];
});
defineAs()メソッドを使用すれば、名前を指定してデータを扱える。
手順2:TopicsTest.php
テストファイル(今回はTopicsTest.php)にテストコードを書く。
class TopicsTest extends TestCase
{
use DatabaseMigrations;
public function testトピックスデータを取得()
{
$data1 = factory(\App\Topics::class, 'first')->create()->toArray();
$data2 = factory(\App\Topics::class, 'second')->create()->toArray();
$expected[] = $data1;
$expected[] = $data2;
$this->topics = new Topics;
$result = $this->topics->fetchAllTopics();
$this->assertEquals($expected, $result);
}
$data1,$data2の説明。
factory()メソッドの第2引数にModelFactoryで指定した名前を使ってデータを指定できる。
また、第3引数に(第2引数が無い場合は、第2引数に)作りたい数を入れればその数のデータを作れる。
テスト用DBを使用するように設定する
手順1:config/database.php
標準で記述されているsqliteの「インメモリ機能」を利用するドライバを追加する。
'connections' => [
(略)
'testing' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
'options' => [
PDO::ATTR_PERSISTENT => true,
],
],
],
手順2:phpunit.xml
.envファイルを使って接続先を変更するため、phpunit.xmlに下記を追記。
<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"/>
<env name="DB_CONNECTION" value="testing"/> // ここ。valueの所に先ほどdatabase.phpで指定したドライバ名を追加。
</php>
手順3:TopicsTest.php
テストファイルに下記を記述。
(今回はTopicsTest.php)
class TopicsTest extends TestCase
{
use DatabaseMigrations;
これでテスト用のデータベースが使用できるようになる。
注意
TopicsTest.phpにuse DatabaseMigrations;を記述しただけの段階でphpunitを実行してしまうと、確認環境のDBがすっ飛ぶので要注意。(作ったテーブルがテーブル毎見事になくなった。笑)
調べてみると、これをしてしまうと全てのmigrationのRunがY→Nになっていた。
$ php artisan migrate:status
+------+------------------------------------------------+
| Ran? | Migration |
+------+------------------------------------------------+
| N | 2014_10_12_000000_create_users_table |
| N | 2014_10_12_100000_create_password_resets_table |
| N | 2017_01_12_164933_create_topics_table |
+------+------------------------------------------------+
なので、
use DatabaseMigrations;
を使う際は、テストに利用するデータベースの接続先を追加してから。
(手順の1と2をきちんとやってから!!!!!)
おまけ
sqliteドライバが使えないということがあったので、その対応も書いておく。
エラー文↓
Symfony\Component\Debug\Exception\FatalThrowableError: Class 'Doctrine\DBAL\Driver\PDOSqlite\Driver' not found
Laravelをインストールして、composer install した時点で
“doctrine/dbal”もインストールされるべきだと思うんだけど…
なんで、laravel のcomposer の依存関係に入ってないんだろう?釈然としない気持ち
artisan migrate で dropColumnがエラーになりハマる – ララ帳より
同感。笑
入れといてくれよって思ったけど、文句を言ってないで入れてみる。
$ composer require doctrine/dbal
これで解決。
以上、Laravel5.3ユニットテストでテスト用DBを使う方法でした。!
要注意事項には気をつけて使用してください!
参考
書籍「Laravelリファレンス: Web職人好みの新世代PHPフレームワーク」