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日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

参考

Tags: codeigniter, codeigniter4, database, testing

CodeIgniter4でCLIコマンドを作成する

この記事は CodeIgniter Advent Calendar 2020 - Qiita の18日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

CodeIgniter4 には CLI コマンドを作成する機能も含まれています。

なお、CodeIgniter3 のように、コントローラを CLI から実行することも可能ですが、この記事では扱いません。

AppInfo コマンドの作成

Custom CLI Commands — CodeIgniter 4.0.4 documentation にある、アプリの情報を表示するコマンドを作成してみます。

ファイルの作成

app/Commands フォルダを作成し、AppInfo.php を作成します。

<?php
namespace App\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;

class AppInfo extends BaseCommand
{
    protected $group = 'demo';
    protected $name = 'app:info';
    protected $description = 'Displays basic application information.';

    public function run(array $params)
    {
    }
}

spark を実行します。

$ php spark 


CodeIgniter CLI Tool - Version 4.0.4 - Server-Time: 2020-12-15 10:08:01am


...

demo
  app:info           Displays basic application information.

コマンドリストの最後に「demo」があり、プロパティに設定した内容が表示されています。

コマンドの実装

run() メソッドにコードを追加します。

<?php

namespace App\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;

class AppInfo extends BaseCommand
{
    protected $group = 'demo';
    protected $name = 'app:info';
    protected $description = 'Displays basic application information.';

    public function run(array $params)
    {
        CLI::write('PHP Version: ' . CLI::color(phpversion(), 'yellow'));
        CLI::write(
            'CI Version: ' . CLI::color(
                \CodeIgniter\CodeIgniter::CI_VERSION,
                'yellow'
            )
        );
        CLI::write('APPPATH: ' . CLI::color(APPPATH, 'yellow'));
        CLI::write('SYSTEMPATH: ' . CLI::color(SYSTEMPATH, 'yellow'));
        CLI::write('ROOTPATH: ' . CLI::color(ROOTPATH, 'yellow'));
        CLI::write(
            'Included files: ' . CLI::color(
                count(get_included_files()),
                'yellow'
            )
        );
    }
}

コマンドの実行

$ php spark app:info
CodeIgniter CLI Tool - Version 4.0.4 - Server-Time: 2020-12-15 10:14:37am

PHP Version: 7.4.13
CI Version: 4.0.4
APPPATH: /Users/kenji/work/codeigniter/ci4-news/app/
SYSTEMPATH: /Users/kenji/work/codeigniter/ci4-news/vendor/codeigniter4/framework/system/
ROOTPATH: /Users/kenji/work/codeigniter/ci4-news/
Included files: 115

アプリの情報が表示されました。

この記事は CodeIgniter Advent Calendar 2020 - Qiita の18日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

参考

Tags: codeigniter, codeigniter4, cli

PHPUnit 6から9の主な変更点

(最終更新:2021-03-05)

この記事は PHP その2 Advent Calendar 2020 - Qiita の17日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

PHPUnit、どんどんバージョンがあがってしまい、変更点がよくわからないので、まとめてみました。

PHPUnit 6

  • 2019/02/08 まで保守(EOL)

6.0

  • PHP 7.0 以上が必要
  • 名前空間
  • setUp()@before の後に実行
  • setUpBeforeClass()@beforeClass の後に実行
  • backupGlobals="false"
  • 廃止
    • --log-json
    • --tap
    • getMock()
    • setExpectedException()
    • setExpectedExceptionRegExp()

6.2

  • @runClassInSeparateProcess 追加

6.4

  • --list-tests 追加

PHPUnit 7

  • 2020/02/07 まで保守(EOL)

7.0

  • PHP 7.1 以上が必要
  • PHP 7.0 のサポート廃止

7.3

  • --order-by 追加
    • --order-by=random
    • --order-by=depends
    • --order-by=reverse

7.5

  • 追加
    • assertEqualsCanonicalizing()
    • assertEqualsIgnoringCase()
    • assertEqualsWithDelta()
    • assertIsArray()
    • assertIsBool()
    • assertIsFloat()
    • assertIsInt()
    • assertIsObject()
    • assertIsString()
    • assertStringContainsString()
    • assertStringContainsStringIgnoringCase()

PHPUnit 8

  • 2021/02/05 まで保守

8.0

  • PHP 7.2 以上が必要
  • PHP 7.1 のサポート廃止

8.3

  • 追加
    • MockBuilder::addMethods()
    • MockBuilder::onlyMethods()

8.4

  • TestCase::createStub() 追加

8.5

  • Xdebug 3 のサポート
  • 追加
    • assertFileEqualsCanonicalizing()
    • assertFileEqualsIgnoringCase()
    • assertStringEqualsFileCanonicalizing()
    • assertStringEqualsFileIgnoringCase()

PHPUnit 9

  • 2022/02/04 まで保守

9.0

  • PHP 7.3 以上が必要
  • PHP 7.2 のサポート廃止
  • 廃止
    • @expectedException*
    • expectExceptionMessageRegExp()
    • assertAttribute*()
    • assertInternalType()
    • assertEquals() のオプションパラメータ
  • MockBuilder::setMethods() が廃止予定

9.1

  • 追加
    • assertIsNotReadable()
    • assertIsNotWritable()
    • assertDirectoryDoesNotExist()
    • assertFileDoesNotExist()
    • assertMatchesRegularExpression()
    • assertDoesNotMatchRegularExpression()

9.2

  • テストダブルのコード生成で Union Type をサポート

9.3

  • PHP 8 のサポート
  • phpunit.xml でのコードカバレッジとロギング設定の変更
  • blacklist/whitelist の変更
    • PHPUnit\Util\ExcludeList 追加
    • PHPUnit\Util\Blacklist 廃止予定
    • TestCase::$backupGlobalsExcludeList 追加
    • TestCase::$backupGlobalsBlacklist 廃止予定
    • TestCase::$backupStaticAttributesExcludeList 追加
    • TestCase::$backupStaticAttributesBlacklist 廃止予定
    • --coverage-filter <directory> 追加
    • --whitelist <directory> 廃止予定
  • パスカバレッジのサポート
    • pathCoverage 属性
    • --path-coverage オプション

この記事は PHP その2 Advent Calendar 2020 - Qiita の17日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

関連

参考

PHPUnit6

PHPUnit7

PHPUnit8

PHPUnit9

Tags: phpunit, testing, php