新しい記事を書きました!
Docker × Laravel テスト用のデータベースコンテナを構築する
Laravel2 Advent Calendar 2019 - Qiita の 16日目 の記事です。
Laravel環境構築
ucan-lab/docker-laravel-alpine を元にLaravel環境を作ります。
$ git clone git@github.com:ucan-lab/docker-laravel-alpine.git
$ cd docker-laravel-alpine
$ make create-project
データベースコンテナ構成
こちらの docker-compose.yml から抜粋です。
db:
image: mysql:8.0
volumes:
- db-store:/var/lib/mysql
- ./logs:/var/log/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
environment:
- MYSQL_DATABASE=${DB_NAME}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASS}
- MYSQL_ROOT_PASSWORD=${DB_PASS}
- TZ=${TZ}
ports:
- ${DB_PORT}:3306
db-testing:
image: mysql:8.0
volumes:
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
tmpfs:
- /var/lib/mysql
- /var/log/mysql
environment:
- MYSQL_DATABASE=${DB_NAME}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASS}
- MYSQL_ROOT_PASSWORD=${DB_PASS}
- TZ=${TZ}
ports:
- ${DB_TESTING_PORT}:3306
db
コンテナが通常の開発用DBコンテナ
db-testing
コンテナがテスト用DBコンテナ
phpunit.xml
vendor/bin/phpunit
を実行すると何も指定しない場合 phpunit.xml
が読み込まれます。
<php>
<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"/>
</php>
<server>
タグを <env>
タグに書き換えます。
<php>
<env name="APP_ENV" value="testing" force="true"/>
<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"/>
</php>
APP_ENV
を docker-compose.yml
にて環境変数として定義していますので、
phpunit.xml
で既存の環境変数の上書きが必要です。
phpunit.xml
でenv
タグやserver
タグを設定すると次のようなPHPコードになるイメージです。
$_ENV['APP_ENV'] = 'testing'; // env タグ
$_SERVER['APP_ENV'] = 'testing'; // server タグ
Dockerを使ってるとココは結構ハマりどころかなと思います。
CreatesApplicationトレイトで一度だけマイグレーションを実行する
テストを書く際は TestCase を継承してテストを作ります。
TestCase
クラスは CreatesApplication トレイトをインポートしてます。
この createApplication()
メソッドは各テスト実行の際に必ず呼ばれるのでこのタイミングで初回のみテスト用データベースのマイグレーションを実行します。
<?php declare(strict_types=1);
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\Artisan;
trait CreatesApplication
{
/**
* @var bool
*/
protected $isSetUpDatabase = false;
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
$this->setUpDatabase();
return $app;
}
/**
* Run migration once
*/
protected function setUpDatabase(): void
{
if ($this->isSetUpDatabase) {
return;
}
Artisan::call('migrate:fresh');
$this->isSetUpDatabase = true;
}
}
テスト実行
$ make app
$ ./vendor/bin/phpunit
参考
- https://phpunit.readthedocs.io/ja/latest/configuration.html
- https://readouble.com/laravel/6.x/ja/testing.html