テスト・開発に使用するデータ生成の必要性
動作確認テストや開発時に使用するデータベースのデータ、どのように準備していますでしょうか?毎回手動で作成している、本番環境から持ってくる。これらは一番良くない例ですよね。
毎回手動で作成していては、開発環境構築の度に、テスト実行の度に作業コストがかかり、オペレーションミスも発生しやすくなります。知っていないと用意できないデータ項目などもあるでしょう。それらを毎回一つ一つ確認するのは大変な作業です。
本番環境のデータを使用することが危険であることは言うまでもないと思います。個人情報を扱っているシステムであれば、情報保護の点から大変なリスクを犯す行為です。メールアドレスを保存してあるシステムであれば、オペレーションミスにより不要なメールを実際に送信してしまう危険性も伴います。
特に、動作確認の際に自動テストを実行する場合、想定通りのデータが入っていないと想定外の結果が出てしまうケースが多々あります。想定通りのデータがないと、確認することのできないテスト項目も存在します。 例えば、「応募後1週間後のユーザにメールを送信する」や「最終ログインから1ヶ月以上経過したユーザにメッセージを表示する」などのテストケース。これらはテスト実行時の画面操作だけでは前提条件を担保することが出来ません。
MagicalGirlの登場
上述の通り、テスト・開発に使用するデータ生成の仕組みが必要とされています。これらのことを解決するために、fixtureを使用したり、RubyであればFactoryGirlなどを利用されていると思います。ですが、PHPで利用できるFactoryGirlのようなライブラリはなく、fixtureを全て手で作成するのはカラム数が巨大だったりする場合など、とても大変な作業です。
そこで、PHPで簡単にデータベースにテストデータをインポートできるライブラリを開発いたしました。 それが「MagicalGirl」です。
MagicalGirlの思想
全てのデータの定義をする必要がない
手動で作成するfixtureはテーブルの1つ1つのカラムに入れる値を個別に設定する必要があります。MagicalGirlでは、全てのカラムの値を人間が定義することは負荷がかかりすぎてしまうと考え、特別に定義したいカラム以外は全て自動的に値を生成するように設計しました。 そのため、特段テストや開発に影響を及ぼさないカラムの値を定義する労力をかけずにたくさんのテストデータを一度に生成することができます。
テストデータ自動生成クラスも自動生成
各テーブルの各カラムそれぞれに適したランダムデータを定義するためには、各テーブル構造にフィットした形のクラス(MagicalGirlではTableImporterという名前のクラスを用意しています)が必要です。そのクラスも手で作成するのは、カラム数が多い場合などなかなか大変な作業になると思います。 そのため、MagicalGirlではテストデータの自動生成クラスも、既に存在するデータベースから自動生成します。
テストデータ自動生成アルゴリズムは各カラム毎にカスタマイズ可能
対象のテーブル構造に合わせたテストデータ自動生成クラスがMagicalGirlによって自動生成されますが、カラムによっては手動でアルゴリズムを変更したいといったケースもあると思います。 MagicalGirlでは、テーブル構造に合わせた自動生成専用のクラスと、ユーザがカスタマイズするためのクラスとに分かれているため、手動定義が必要なカラムのみを柔軟にカスタマイズすることが出来ます。
テーブル構造の変化にも対応
活発に開発されているシステムでは、テーブル構造の変更が発生することもありますが、そのような場合でも自動生成コマンドの再実行により、簡単に新しいテーブル構造に対応させることが出来ます。 このとき、ユーザがカスタマイズするように用意されたクラスの方には変更を加えないため、開発し直しといったことも発生しません。
毎回同じデータを挿入したいマスタデータにも対応
毎回同じデータを入れたいマスタデータなど、自動生成されたりプログラムを書いたりするのがかえって大変といった場合があります。そのようなユースケースにも備え、TSV形式で用意したファイルをそのままテーブルに取り込む仕組みも用意しました。
新たな設定ファイルを増やさない
MagicalGirlのミッションは、既に存在するシステムのテストデータを生成することです。ですので、MagicalGirlのために新たな設定ファイルが増えないように考えて開発しました。
DB接続設定は新たな設定ファイルを用意することなく、今まで使用していた設定ファイルをそのまま共同で使用することができます。
MagicalGirlを使ってみる
環境
MagicalGirlは下記の環境で動作確認をしております。
- PHP 5.6
- MySQL 5.6
上記環境でないと動作しないということではないので、別の環境であったとしてもまずはお試しいただければと思います。
ソース
GitHubで管理しています。
https://github.com/magical-yuri/magical-girl
インストール
Composerを使ってインストールできます。
Composerをインストールする
$ curl -s http://getcomposer.org/installer | php
composer.jsonファイルの用意
{ "require-dev": { "phpunit/phpunit": "*", "magical-yuri/magical-girl": "*" }, "config": { "bin-dir": "bin/" } }
MagicalGirlのインストール
$ php composer.phar install
準備
初期化
下記コマンドを実行して、MagicalGirl実行に必要なディレクトリ、ファイルを作成します。
$ bin/magicalinit
データベースの接続設定
'lib/DB/DBConnections.php'ファイルを修正し、DBホスト、DB名、DBパスワードを取得するためのメソッドを実装します。既存システムで使っている設定ファイルが存在するかと思いますので、その設定ファイルの内容を読み込むように実装してください。
例えば、下記のように実装します。
protected static function getExampleHost() { return '127.0.0.1'; } protected static function getExampleUserName() { return 'user_name'; } protected static function getExamplePassword() { return 'password'; }
各テーブル専用のTableImporterクラスの生成
下記コマンドの実行により、実行時のテーブル構造から適切なテストデータ自動生成クラス(TableImporterクラス)を自動生成します。
$ bin/magicalgen [databaseName] [tableName]
コマンドを実行すると、下記の2つのファイルが生成されます。
- lib/DB/TableImporter/[schemaName]/[databaseName][tableName]Importer.php
- lib/DB/TableImporter/[schemaName]/base/Base[schemaName][tableName]Importer.php
ここで、baseディレクトリ中のファイルには変更を加えないようご注意下さい。baseディレクトリ中のファイルは、上記コマンド実行の度に実行時のテーブル構造に合わせて書き換えてしまうため、このファイルへの変更は全て消えてしまいます。
個別のカラムのデータ生成アルゴリズムをカスタマイズしたい場合は、lib/DB/TableImporter/[schemaName]ディレクトリ直下のファイルのみを修正してください。
マスタデータの準備
マスタデータはヘッダーなしのTSVファイル形式で用意します。 ディレクトリ、ファイル名は下記のように定義してください。
masterData └── [databaseName] ├── [tableName1].tsv ├── [tableName2].tsv └── [tableName3].tsv
masterDataディレクトリの中に各データベース名のディレクトリを用意し、その中に各テーブル毎のTSVファイルを用意します。TSVファイル名は、テーブル名.tsvとしてください。
このTSVファイルは、既にデータの入っているテーブルであれば下記コマンドで取得できます。
$ mysql -h 127.0.0.1 -u user -p -B -N -e 'select * from [tableName1]' [databaseName] > [tableName1].tsv
利用方法
上記で準備したTableImporterクラスとマスタデータのTSVを利用して、下記のように実装します。
<?php // Composerのautoloadを利用して、MagicalGirlのライブラリを読み込む require_once(__DIR__ . '/vendor/autoload.php'); use MagicalGirl\TestDBImporter\TestDBImporter; use MagicalGirl\TestDBImporter\MasterDBImporter; // magicalgenコマンドで生成したTableImporterクラスをrequireする require_once(__DIR__ . '/lib/DB/TableImporter/test/TestTable1Importer.php'); require_once(__DIR__ . '/lib/DB/TableImporter/test/TestTable2Importer.php'); class MyDBImporter extends TestDBImporter { public function import() { // 各テーブルに合わせたImporterクラスのインスタンスを生成する $table1Importer = new TestTable1Importer(); $table2Importer = new TestTable2Importer(); // 各テーブルに20行ずつデータを挿入する for ($i = 0; $i < 20; $i++) { $table1Row = $table1Importer->addRow(); $table2Row = $table2Importer->addRow( array( 'table1_id' => $table1Row['id'] ) ); } } } // 通常下記は別ファイルに記述します // TSVファイルからマスタデータをImportする $importer = new MasterDBImporter(); $importer->import(); // 上記定義クラスを利用してトランザクションデータをImportする $importer = new MyDBImporter(); $importer->import();
さいごに
GitHubで公開中のREADME.mdファイルにて、上述の利用手順の他簡単なAPIも掲載しておりますのでこちらもご参考にしてください。
PHPで開発中のエンジニアにとって、MagicalGirlはきっと助けになると思います。MagicalGirlを使って、快適な開発・テストデータの作成を実感してみてください。