CodeIgniter4でテストDBをMySQLにする
この記事は CodeIgniter Advent Calendar 2020 - Qiita の19日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。
CodeIgniter4のフィーチャーテストでモックを使う の続きです。
テスト用のデータベースはデフォルトの SQLite3 のメモリデータベースを使っていましたが、それを開発環境に合わせて MySQL に変更します。
テスト用データベースの作成
テスト用のデータベースを作成します。
$ mysql -uroot -p
テスト用データベース ci4tutorial_test
を作成します。
CREATE DATABASE ci4tutorial_test DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
アプリ用のデータベースユーザ dbuser
に権限を与えます。
GRANT ALL PRIVILEGES ON ci4tutorial_test.* TO dbuser@localhost;
データベース接続設定
テストデータベースに接続するための設定が必要です。
環境固有の設定と考え、.env
で設定することにします。
phpunit.xml
phpunit.xml
での環境変数の設定を削除(コメントアウト)します。
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -52,7 +52,7 @@
<!-- <env name="database.tests.password" value=""/> -->
<!-- <env name="database.tests.DBDriver" value="MySQLi"/> -->
<!-- <env name="database.tests.DBPrefix" value="tests_"/> -->
- <env name="database.tests.database" value=":memory:"/>
- <env name="database.tests.DBDriver" value="SQLite3"/>
+<!-- <env name="database.tests.database" value=":memory:"/> -->
+<!-- <env name="database.tests.DBDriver" value="SQLite3"/> -->
</php>
</phpunit>
.env
.env
に以下の設定を追加します。
database.tests.hostname = localhost
database.tests.database = ci4tutorial_test
database.tests.username = dbuser
database.tests.password = dbpassword
database.tests.DBDriver = MySQLi
app/Config/Database.php
テーブル名のプリフィックスは必要ないので、空文字に変更します。
これで、開発用とテスト用のテーブル名が同一になります。
--- a/app/Config/Database.php
+++ b/app/Config/Database.php
@@ -64,7 +64,7 @@ class Database extends \CodeIgniter\Database\Config
'password' => '',
'database' => ':memory:',
'DBDriver' => 'SQLite3',
- 'DBPrefix' => 'db_', // Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE FOR CI DEVS
+ 'DBPrefix' => '',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'cacheOn' => false,
テストの実行
phpunit
を実行します。
$ vendor/bin/phpunit tests/feature/NewsTest.php
PHPUnit 8.5.13 by Sebastian Bergmann and contributors.
Error: XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set
.. 2 / 2 (100%)
Time: 459 ms, Memory: 12.00 MB
OK (2 tests, 7 assertions)
通りました。
データベース内のデータの確認
MySQL に接続して中身のデータを確認しておきます。
mysql> use ci4tutorial_test;
mysql> select * from news \G
*************************** 1. row ***************************
id: 1
title: Elvis sighted
slug: elvis-sighted
body: Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app.
*************************** 2. row ***************************
id: 2
title: Say it isn't so!
slug: say-it-isnt-so
body: Scientists conclude that some programmers have a sense of humor.
*************************** 3. row ***************************
id: 3
title: Caffeination, Yes!
slug: caffeination-yes
body: World's largest coffee shop open onsite nested coffee shop for staff only.
3 rows in set (0.01 sec)
ci4tutorial_test.news
テーブルにデータが挿入されています。
データベースのリフレッシュをやめる
テストメソッドごとにデータベースをリフレッシュするのは重いのでやめてみます。
(2021-02-23 追記) CodeIgniter 4.0.5以降にはマイグレーションを実行しない設定やマイグレーションやシーダーを一度だけ実行する設定が追加されました。
ます、テスト用の NewsSeeder
を以下のように作成します。
tests/_support/Database/Seeds/NewsSeeder.php
<?php
namespace Tests\Support\Database\Seeds;
use CodeIgniter\Database\Seeder;
class NewsSeeder extends Seeder
{
public function run()
{
$table = 'news';
$this->db->table($table)->truncate();
$data = [
[
'title' => 'Elvis sighted',
'slug' => 'elvis-sighted',
'body' => 'Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app.',
],
];
$this->db->table($table)->insertBatch($data);
}
}
テストコードを変更します。
--- a/tests/feature/NewsTest.php
+++ b/tests/feature/NewsTest.php
@@ -3,16 +3,16 @@
namespace Tests\Feature;
use App\Models\NewsModel;
+use Tests\Support\Database\Seeds\NewsSeeder;
use CodeIgniter\Database\ModelFactory;
use CodeIgniter\Test\FeatureTestCase;
class NewsTest extends FeatureTestCase
{
- protected $refresh = true;
+ protected $refresh = false;
protected $namespace = 'App';
- protected $basePath = APPPATH . 'Database';
- protected $seed = 'NewsSeeder';
+ protected $seed = NewsSeeder::class;
public function testGetNews()
{
$refresh
は false に設定しても migration は setUp()
内で実行されます(Pull Request #3221 参照)。
$basePath
を削除すればデフォルトの tests/_support/Database/Seeds/
以下を探すようになります。
これで、毎回リフレッシュすることはなくなりました。
この記事は CodeIgniter Advent Calendar 2020 - Qiita の19日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。
参考
Date: 2020/12/19