0 フォロワー

フィクスチャ

フィクスチャはテストの重要な部分です。主な目的は、テストが反復可能で、期待どおりに実行されるように、固定/既知の状態に環境を設定することです。Yii は、フィクスチャを正確に定義し、Codeception でテストを実行するときと独立して簡単に使用できるフィクスチャフレームワークを提供します。

Yii フィクスチャフレームワークの重要な概念は、いわゆるフィクスチャオブジェクトです。フィクスチャオブジェクトは、テスト環境の特定の側面を表し、yii\test\Fixture またはその子クラスのインスタンスです。たとえば、UserFixture を使用して、ユーザー DB テーブルに固定されたデータセットが含まれていることを確認できます。テストを実行する前に1つまたは複数のフィクスチャオブジェクトをロードし、終了時にそれらをアンロードします。

フィクスチャは、yii\test\Fixture::$depends プロパティを介して指定された他のフィクスチャに依存する場合があります。フィクスチャがロードされると、それが依存するフィクスチャはフィクスチャの前に自動的にロードされ、フィクスチャがアンロードされると、依存するフィクスチャはフィクスチャの後にアンロードされます。

フィクスチャの定義

フィクスチャを定義するには、yii\test\Fixture または yii\test\ActiveFixture を拡張して新しいクラスを作成します。前者は汎用フィクスチャに最適ですが、後者はデータベースと ActiveRecord を操作するように特別に設計された拡張機能を持っています。

次のコードは、User ActiveRecord と対応する user テーブルに関するフィクスチャを定義します。

<?php
namespace app\tests\fixtures;

use yii\test\ActiveFixture;

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

ヒント: ActiveFixtureは、テスト目的でDBテーブルを準備するためのものです。テーブルは、yii\test\ActiveFixture::$tableNameプロパティまたはyii\test\ActiveFixture::$modelClassプロパティのいずれかを設定して指定できます。後者の場合、テーブル名はmodelClassで指定されたActiveRecordクラスから取得されます。

注意: yii\test\ActiveFixtureはSQLデータベースにのみ適しています。NoSQLデータベースの場合、Yiiは以下のActiveFixtureクラスを提供します。

  • Mongo DB: yii\mongodb\ActiveFixture
  • Elasticsearch: yii\elasticsearch\ActiveFixture (バージョン2.0.2以降)

ActiveFixtureフィクスチャのフィクスチャデータは通常、fixturepath/data/tablename.phpにあるファイルで提供されます。ここで、fixturepathはフィクスチャクラスファイルを含むディレクトリを表し、tablenameはフィクスチャに関連付けられたテーブルの名前です。上記の例では、ファイルは@app/tests/fixtures/data/user.phpである必要があります。データファイルは、ユーザーテーブルに挿入されるデータ行の配列を返す必要があります。例えば、

<?php
return [
    'user1' => [
        'username' => 'lmayert',
        'email' => 'strosin.vernice@jerde.com',
        'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
        'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
    ],
    'user2' => [
        'username' => 'napoleon69',
        'email' => 'aileen.barton@heaneyschumm.com',
        'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
        'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
    ],
];

行にエイリアスを付けることで、テストでそのエイリアスを使用して行を参照することができます。上記の例では、2つの行にはそれぞれuser1user2というエイリアスが付けられています。

また、自動インクリメント列のデータを指定する必要はありません。フィクスチャがロードされると、Yiiは自動的に実際の値を行に設定します。

ヒント: yii\test\ActiveFixture::$dataFileプロパティを設定することで、データファイルの場所をカスタマイズできます。また、yii\test\ActiveFixture::getData()をオーバーライドしてデータを提供することもできます。

前述のように、フィクスチャは他のフィクスチャに依存する場合があります。たとえば、UserProfileFixtureは、ユーザープロファイルテーブルにユーザーテーブルを指す外部キーが含まれているため、UserFixtureに依存する必要がある場合があります。依存関係は、以下のようにyii\test\Fixture::$dependsプロパティを介して指定されます。

namespace app\tests\fixtures;

use yii\test\ActiveFixture;

class UserProfileFixture extends ActiveFixture
{
    public $modelClass = 'app\models\UserProfile';
    public $depends = ['app\tests\fixtures\UserFixture'];
}

依存関係は、フィクスチャが明確に定義された順序でロードおよびアンロードされることも保証します。上記の例では、外部キー参照がすべて存在するように、UserFixtureが常にUserProfileFixtureの前にロードされ、同じ理由でUserProfileFixtureがアンロードされた後にアンロードされます。

上記では、DBテーブルに関するフィクスチャを定義する方法を示しました。DBに関連しないフィクスチャ(特定のファイルとディレクトリに関するフィクスチャなど)を定義するには、より一般的な基本クラスyii\test\Fixtureを拡張し、load()およびunload()メソッドをオーバーライドできます。

フィクスチャの使用

コードをテストするためにCodeceptionを使用している場合は、フィクスチャのロードとアクセスに対する組み込みサポートを使用できます。

他のテストフレームワークを使用している場合は、テストケースでyii\test\FixtureTraitを使用して同じ目標を達成できます。

以下では、Codeceptionを使用してUserProfileユニットテストクラスを作成する方法について説明します。

\Codeception\Test\Unitを拡張するユニットテストクラスで、_fixtures()メソッドで使用するフィクスチャを宣言するか、アクターのhaveFixtures()メソッドを直接使用します。例:

namespace app\tests\unit\models;


use app\tests\fixtures\UserProfileFixture;

class UserProfileTest extends \Codeception\Test\Unit
{   
    public function _fixtures()
    {
        return [
            'profiles' => [
                'class' => UserProfileFixture::class,
                // fixture data located in tests/_data/user.php
                'dataFile' => codecept_data_dir() . 'user.php'
            ],
        ];
    }

    // ...test methods...
}

_fixtures()メソッドにリストされているフィクスチャは、テストが実行される前に自動的にロードされます。また、前述のように、フィクスチャがロードされると、そのすべての依存フィクスチャが最初に自動的にロードされます。上記の例では、UserProfileFixtureUserFixtureに依存しているため、テストクラスでテストメソッドを実行すると、2つのフィクスチャが順番にロードされます:UserFixtureUserProfileFixture

_fixtures()haveFixtures()の両方にフィクスチャを指定する場合、クラス名または構成配列を使用してフィクスチャを参照できます。構成配列を使用すると、フィクスチャがロードされたときにフィクスチャのプロパティをカスタマイズできます。

フィクスチャにエイリアスを割り当てることもできます。上記の例では、UserProfileFixtureprofilesというエイリアスが付けられています。テストメソッドでは、grabFixture()メソッドでエイリアスを使用してフィクスチャオブジェクトにアクセスできます。例:

$profile = $I->grabFixture('profiles');

は、UserProfileFixtureオブジェクトを返します。

UserProfileFixtureActiveFixtureを拡張しているため、さらに次の構文を使用してフィクスチャによって提供されるデータにアクセスできます。

// returns the UserProfile model corresponding to the data row aliased as 'user1'
$profile = $I->grabFixture('profiles', 'user1');
// traverse data in the fixture
foreach ($I->grabFixture('profiles') as $profile) ...

フィクスチャクラスとデータファイルの整理

デフォルトでは、フィクスチャクラスは、フィクスチャクラスファイルを含むフォルダーのサブフォルダーであるdataフォルダーの下に対応するデータファイルを探します。単純なプロジェクトで作業する場合は、この規約に従うことができます。大規模なプロジェクトでは、異なるテストのために同じフィクスチャクラスに対して異なるデータファイルを切り替える必要性が頻繁に発生する可能性があります。したがって、クラス名前空間と同様の階層的な方法でデータファイルを整理することをお勧めします。例えば、

# under folder tests\unit\fixtures

data\
    components\
        fixture_data_file1.php
        fixture_data_file2.php
        ...
        fixture_data_fileN.php
    models\
        fixture_data_file1.php
        fixture_data_file2.php
        ...
        fixture_data_fileN.php
# and so on

このようにすることで、テスト間のフィクスチャデータファイルの衝突を回避し、必要に応じて使用できます。

注意: 上記の例では、フィクスチャファイルは例示目的でのみ名前が付けられています。実際には、フィクスチャクラスが拡張しているフィクスチャクラスに応じて名前を付ける必要があります。たとえば、DBフィクスチャ用にyii\test\ActiveFixtureを拡張している場合は、DBテーブル名をフィクスチャデータファイル名として使用する必要があります。MongoDBフィクスチャ用にyii\mongodb\ActiveFixtureを拡張している場合は、コレクション名をファイル名として使用する必要があります。

同様の階層を使用して、フィクスチャクラスファイルを整理できます。dataをルートディレクトリとして使用する代わりに、データファイルとの競合を避けるために、fixturesをルートディレクトリとして使用できます。

yii fixtureによるフィクスチャの管理

Yiiは、yii fixtureコマンドラインツールを介してフィクスチャをサポートします。このツールは以下をサポートしています。

  • RDBMS、NoSQLなど、さまざまなストレージへのフィクスチャのロード。
  • さまざまな方法でのフィクスチャのアンロード(通常はストレージのクリアです)。
  • フィクスチャの自動生成とランダムデータによる投入。

フィクスチャデータ形式

ロードするフィクスチャデータがあると仮定しましょう。

#users.php file under fixtures data path, by default @tests\unit\fixtures\data

return [
    [
        'name' => 'Chase',
        'login' => 'lmayert',
        'email' => 'strosin.vernice@jerde.com',
        'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
        'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
    ],
    [
        'name' => 'Celestine',
        'login' => 'napoleon69',
        'email' => 'aileen.barton@heaneyschumm.com',
        'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
        'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
    ],
];

データベースにデータをロードするフィクスチャを使用している場合、これらの行はusersテーブルに適用されます。たとえば、mongodbフィクスチャのようなnosqlフィクスチャを使用している場合、このデータはusersmongodbコレクションに適用されます。さまざまなローディング戦略の実装などについて詳しく知りたい場合は、公式のドキュメントを参照してください。上記のフィクスチャの例は、yii2-faker拡張機能によって自動生成されたものです。詳細については、これらのセクションを参照してください。フィクスチャクラスの名前は複数形にしないでください。

フィクスチャのロード

フィクスチャクラスにはFixtureというサフィックスを付ける必要があります。デフォルトでは、フィクスチャはtests\unit\fixtures名前空間の下で検索されます。この動作は、構成またはコマンドオプションで変更できます。-Userのように、名前の前に-を指定して、ロードまたはアンロードする一部のフィクスチャを除外できます。

フィクスチャをロードするには、次のコマンドを実行します。

注意: データをロードする前に、アンロードシーケンスが実行されます。通常、これにより、以前のフィクスチャ実行によって挿入された既存のデータがすべてクリアされます。

yii fixture/load <fixture_name>

必須のfixture_nameパラメーターは、データがロードされるフィクスチャの名前を指定します。一度に複数のフィクスチャをロードできます。以下は、このコマンドの正しい形式です。

// load `User` fixture
yii fixture/load User

// same as above, because default action of "fixture" command is "load"
yii fixture User

// load several fixtures
yii fixture "User, UserProfile"

// load all fixtures
yii fixture/load "*"

// same as above
yii fixture "*"

// load all fixtures except ones
yii fixture "*, -DoNotLoadThisOne"

// load fixtures, but search them in different namespace. By default namespace is: tests\unit\fixtures.
yii fixture User --namespace='alias\my\custom\namespace'

// load global fixture `some\name\space\CustomFixture` before other fixtures will be loaded.
// By default this option is set to `InitDbFixture` to disable/enable integrity checks. You can specify several
// global fixtures separated by comma.
yii fixture User --globalFixtures='some\name\space\Custom'

フィクスチャのアンロード

フィクスチャをアンロードするには、次のコマンドを実行します。

// unload Users fixture, by default it will clear fixture storage (for example "users" table, or "users" collection if this is mongodb fixture).
yii fixture/unload User

// Unload several fixtures
yii fixture/unload "User, UserProfile"

// unload all fixtures
yii fixture/unload "*"

// unload all fixtures except ones
yii fixture/unload "*, -DoNotUnloadThisOne"

namespaceglobalFixturesのような同じコマンドオプションもこのコマンドに適用できます。

グローバルなコマンドの構成

コマンドラインオプションを使用すると、フィクスチャコマンドをオンザフライで構成できますが、コマンドを一度だけ構成したい場合もあります。たとえば、次のように異なるフィクスチャパスを構成できます。

'controllerMap' => [
    'fixture' => [
        'class' => 'yii\console\controllers\FixtureController',
        'namespace' => 'myalias\some\custom\namespace',
        'globalFixtures' => [
            'some\name\space\Foo',
            'other\name\space\Bar'
        ],
    ],
]

フィクスチャの自動生成

Yiiは、テンプレートに基づいてフィクスチャを自動生成することもできます。異なる言語と形式で異なるデータを使用してフィクスチャを生成できます。この機能は、Fakerライブラリとyii2-faker拡張機能によって行われます。詳細については、拡張機能ガイドを参照してください。

まとめ

上記では、フィクスチャを定義および使用する方法について説明しました。以下に、DB関連の単体テストを実行する一般的なワークフローをまとめます。

  1. yii migrateツールを使用して、テストデータベースを最新バージョンにアップグレードします。
  2. テストケースを実行します。
    • フィクスチャをロードします。関連するDBテーブルをクリーンアップし、フィクスチャデータを投入します。
    • 実際のテストを実行します。
    • フィクスチャをアンロードします。
  3. すべてのテストが完了するまで、手順2を繰り返します。

スペルミスを見つけましたか、このページを改善する必要があると思いますか?
githubで編集する !