14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Fakerで自動テスト用のダミーデータ作成を自動化する

Last updated at Posted at 2014-12-24

データベースを含んだ自動テストは面倒ですね。なにが面倒って、テスト用のデータ、いわゆるフィクスチャを準備するのがもう。

Yii はデータベースの結果をモックする純粋なロジックテストではなく、ファンクショナルテストやデータベース込みのテストを指向しています。2.0 になって、BDDふうのテスティングフレームワーク Codeception のテストプロジェクトが一式ついてくるようになりました。BDD ふうにページをテストするにはホンモノが動くことが前提、つまりデータベースも当然要るわけです。

フィクスチャはすべて手書きしてもいいのですが、たとえば 21 件以上でページネーションすることを試そうと思ったら...

というわけで Faker を活用しましょう。

Yii のプロジェクトテンプレートの tests フォルダ以下には、テスト環境専用の codeception\bin\yii コマンドが置いてあり、こんな感じで、フィクスチャのサポートが追加で組み込まれています。

$config = yii\helpers\ArrayHelper::merge(
    // ... ,
    [
        'controllerMap' => [
            'fixture' => [
                'class' => 'yii\faker\FixtureController',
                'fixtureDataPath' => '@tests/codeception/fixtures/data',
                'templatePath' => '@tests/codeception/templates',
                'namespace' => 'tests\codeception\fixtures',
            ],
        ],
    ]
);

設定にしたがって tests/codeception/templates にフィクスチャのテンプレートを書きます。たとえばユーザー用のフィクスチャなら templates/user.php にこう書きます。

<?php
/**
 * @var $faker \Faker\Generator
 * @var $index integer
 */
return [
    'email' => $faker->email,
    'password_hash' => Yii::$app->security->generatePasswordHash('password_' . $index),
    'auth_key' => Yii::$app->security->generateRandomString(),
    'name' => $faker->firstName . ' ' . $faker->lastName,
    'birthday' => $faker->date(),
    'created_at' => $faker->unixTime,
    'updated_at' => $faker->unixTime,
];

$faker からプロパティを取ると、取り出すたびにデタラメなそれらしいデータが出てきます。ランダムだと困るものは、 $index を使うと計算で出したり決まった配列から取り出したりできます。

で、 tests/codeception/bin/yii fixture/generate user を実行するとテンプレートのパスとデータのパスが設定してあるので...

$ tests/codeception/bin/yii fixture/generate user
Fixtures will be generated under the path: 
        /.../tests/codeception/fixtures/data

Templates will be taken from path: 
        /.../tests/codeception/templates

        * user
Generate above fixtures? (yes|no) [no]: yes
The following fixtures template files were generated:

        * user

はい、これでできました。じゃーん!

<?php

return [
    [
        'email' => 'pauline22@weber.info',
        'password_hash' => '$2y$13$kU/MfgI/XUD6JacW7VFe2O3iab3pksTEvrXaJ9c0mof86lnNEJwW.',
        'auth_key' => 'l7iv336Q00OrP0Mcn7sUgvbUAhd3gU1W',
        'name' => 'Ophelia Jacobs',
        'birthday' => '1980-09-09',
        'created_at' => 602074437,
        'updated_at' => 390537715,
    ],
    [
        'email' => 'kacie78@yahoo.com',
        'password_hash' => '$2y$13$ry7b0lKIcY1grUQmQBkjgupbRsNxAnoOsAgOwJsxgXQCnlljYM3W6',
        'auth_key' => 'Ux5iYaPTpY5pgym9fuwEjrZXOCdZbXO5',
        'name' => 'Audra Cole',
        'birthday' => '2010-05-17',
        'created_at' => 447193310,
        'updated_at' => 293260057,
    ],
];

2個じゃ足りないなら、

tests/codeception/bin/yii fixture/generate user --count=10

で、こういうのが 10 件でも 20 件でも作れます。

本当にバラバラなデータを手で作るのは面倒だし、人間が手でやるとどうしても恣意的になってしまいます。思い込みでテストケースの漏れが出てくることもあります。

テンプレートから生成することのメリットとして、再現性のないパスワードハッシュを固定できるというのもあります。フィクスチャデータで generatePasswordHash を呼ぶと、セキュリティの都合で実際には毎回違うデータになってしまいます。細かいことかもしれませんが、フィクスチャデータで値を生成すると、場合によっては失敗を再現できないかもしれません。フィクスチャデータはテストコードの一部です。

というわけで、テンプレートがあるからといって、フィクスチャデータをバージョン管理しないというのはナシです。テストがグリーンでコミットしたことを確実に示すために、フィクスチャはバージョン管理しましょう。

バージョン管理するということは、もうこのデータは開発者のものです。生成し直すまで、好きなように編集して、都合の悪いところは適当に書き換えましょう。多対多テーブルなんかは、テンプレートを書かずにフィクスチャを直接書いてもいいかもしれません。

フィクスチャデータを使うには、クラスを定義しなければなりません。といっても、AssetBundle 並みに非常に簡単な実装です。テスト用 yii
コマンドの FixtureControllernamespace が指すところに...

<?php
namespace tests\codeception\fixtures;

use yii\test\ActiveFixture;

class UserFixture extends ActiveFixture
{
    public $modelClass = 'app\models\User';
    public $depends = [];
} 

$modelClass はどのテーブルにロードするかという情報を引くための ActiveRecord クラスです。

$depends には、このフィクスチャをロードする前にロードして欲しい他のフィクスチャのクラス名を複数登録します。まさに AssetBundle のノリですね。これで、ロード時に外部キーの先がないなんてこともありません。

これでデータをロードすることができるようになりました。自動テストを実行する前に、作ったデータが実際にデータベース入るかどうかを確認しておきます。テスト用のデータベースをマイグレーションして、そこにすべてのフィクスチャを流し込みます。

tests/codeception/bin/yii migrate/up
tests/codeception/bin/yii fixture/load "*"

成功したらOKです。外部キー制約や文字数制限などの都合で入らないフィクスチャを作っていると、テストでも使うことができません。確認し終わったらアンロードします。

tests/codeception/bin/yii fixture/unload "*"

さて、ここまでやってもらえればもうあとはモチベーションを下げるヤツはいません。自動テストをサクサク書いていきましょう。

時間もないので、各種のテストでどうやってロードするかは、マニュアルを参照したり、アプリケーションテンプレートから読み取ったりしてください。

なお、Faker は一般的な道具なので、Laravel でも Symfony でも使えます。Packagist には CakePHP3 のプラグインも見かけました。

Laravel で Faker を使う場合は Jeff の記事を参照して下さい。

メリー・クリスマス

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?