LoginSignup
9
11

More than 5 years have passed since last update.

Laravel5.3ユニットテストでテスト用DBを使う方法~要注意事項付き~

Last updated at Posted at 2017-02-07

ユニットテストを行うときは本番用の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件〜で作って大丈夫。)

ModelFactory.php
$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)にテストコードを書く。

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の「インメモリ機能」を利用するドライバを追加する。

database.php
'connections' => [

          

        'testing' => [
            'driver' => 'sqlite',
            'database' => ':memory:',
            'prefix' => '',
            'options' => [
                PDO::ATTR_PERSISTENT => true,
            ],
        ],

    ],

手順2:phpunit.xml

.envファイルを使って接続先を変更するため、phpunit.xmlに下記を追記。

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フレームワーク」

9
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11