2018.01.29

LaravelのテストでインメモリSQLiteを使う


ユニットテストの際にインメモリの SQLite を使用することで、開発用のデータベースに影響を与えることなくテストを実行することができます。

前提

PHP Laravel PHPUnit
v7.2 v5.5 v6.5.5

セットアップ

まずはデータベースの接続設定を config/database.php に追加します。 database の項目に :memory: を指定するのがポイントですね。 これによりデータの保存先がメモリ上になるようです。

config/database.php
return [
    /* 中略 */
    'connections' => [
        'sqlite_testing' => [
            'driver' => 'sqlite',
            'database' => ':memory:',
            'prefix' => '',
        ],
        /* 中略 */
    ],
    /* 中略 */
];

次にPHPUnitの設定を行います。<env> にて環境変数が指定されるので、DB_CONNECTION を追加し、値を上記で追加したキー sqlite_testing としています。

phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
    <!-- 中略 -->
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="DB_CONNECTION" value="sqlite_testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
    </php>
</phpunit>

プロジェクト作成直後のデフォルトコードで、すでに以下のように環境変数から接続先のデータベースを指定しています。

config/database.php
'default' => env('DB_CONNECTION', 'mysql'),

そのため、phpunit.xmlDB_CONNECTION を設定してやるとテスト実行時のみデータベースを切り替えられるわけです。

テストコード

tests/Unit/ExampleTest.php
<?php

namespace Tests\Unit;

use App\User;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 各テスト実行前に呼ばれる。
     *
     */
    protected function setUp()
    {
        parent::setUp();

        // データベースマイグレーション
        $this->artisan('migrate');

        // 必要に応じてテストデータ挿入
        $this->seed('ExampleTableSeeder');
    }

    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $user = User::create([
            'name' => 'John Doe',
            'email' => 'john@doe.com',
            'password' => 'testing1234',
        ]);

        $this->assertEquals(1, User::all()->count());
    }
}

PHPUnitでは各テスト実行前に setUp メソッドが呼び出されます。この setUp メソッド内でマイグレーションおよび Seeder を実行しています。

Seeder の実行はお好みで、アプリの動作前提となるマスタデータなどを入れると良いでしょう。コマンドで言えば、以下を実行しているのと同じですね。

$ php artisan migrate
$ php artisan db:seed --class=ExampleTableSeeder

以上、LaravelのテストでインメモリSQLiteを使う方法でした。