データを取り扱う
テストはお互いに影響を及ぼし合ってはなりません。これが大雑把なルールです。 テストがデータベースとやり取りする際に内部のデータを変更しかねないため、最終的にデータの不一致や矛盾を生じさせるかもしれないのです。テストはすでに挿入されているレコードを挿入したり、削除されているレコードを検索しようとするかもしれません。テストの失敗を回避するため、データベースは各テストを行う前に初期状態になっていなければなりません。Codeceptionには、データをクリーンにするための方法やアプローチがいくつか存在します。
この章では、前章のクリーンアップに関する注意を要約するとともに、データストレージバックエンドを選択する方法の最善策について提案します。
私たちがデータベースをクリーンアップすると決めた時、私たちはそれをできるだけ速く行うべきです。テストは常に速く実行される必要があります。データベースを一から再構築するのは最良の方法とは言えないかもしれませんが、唯一の方法とも言えるかもしれません。いずれにせよ、テストのためだけに特別なデータベースを使用してください。絶対に開発環境または本番環境のデータベースでテストを実行しないでください!
自動クリーンアップ
Codeceptionにはデータベースと対話をする際に必要なほとんどのタスクを行ってくれるDb
モジュールがあります。デフォルトでは、dumpからデータベースを再構築し、各テストが終了した後にクリーンアップを試みます。このモジュールのデータベースのdumpはSQLフォーマットです。codeception.yml
内ですでに設定が準備されています。
modules:
config:
Db:
dsn: 'PDO DSN HERE'
user: 'root'
password:
dump: tests/_data/your-dump-name.sql
あなたのテストスイートでこのモジュールを有効化したら、自動的にdumpからデータベースにデータが挿入され、各テストの実行時に再構築されます。これらの設定はpopulate
と cleanup
オプションの変更によってfalse
に設定することができます。
Db
モジュールはラフなツールです。PDOでサポートされているどのデータベースでも動作します。もし速度が遅くなければ、すべてのテストで使用できます。dumpをロードするのはとても時間がかかりますが、他の手段を使うこともできます。機能テストや単体テストを行う際などにアプリケーションとテストがデータベース接続を共有している時、速度を向上させる最善策はすべてのコードをトランザクションに設置し、テスト終了時にロールバックすることです。
分離された接続
受け入れテストでは、異なるデータベース接続が使用されているため、テスト速度を向上するにはSQLiteファイルのデータベースを使うことができます。また、代替案として、各テストごとにデータベースを作成するのを避け、テスト終了後にすべてのアップデートをクリーンアップすることも考えられます。Dbモジュールはあなたのアプリケーションと同等の機能を提供しており、アサーション(seeInDatabase
アクション)のためにデータベースにアクセスしたり、自動クリーンアップしたりします。
共有された接続
あなたのアプリケーションもしくはその一部がCodeceptionプロセス内で実行されている場合、アプリケーション接続をテストで使用することが可能です。接続にアクセスできれば、すべてのデータベース操作はグローバルトランザクションに含むことができ、最後にロールバックされます。それは劇的にパフォーマンスを改善するでしょう。最後にデータベースに何も書かれないため、実際にデータベースの再構築が必要とならないのです。
ORM モジュール
アプリケーションがDoctrineやDoctrine2のようなORMを使用しているのでしたら、各モジュールでスイートに接続してください。デフォルトでは、トランザクション内のすべてをカバーします。もしあなたが複数のデータベース接続を使っていない、もしくはORMによって追跡されないトランザクションである場合、このモジュールはあなたの役には立たないでしょう。
ORMモジュールはDb
モジュールと接続できますが、デフォルトでは両方ともクリーンアップを行います。従って、あなたが明示的に使用しているモジュールを設定する必要があります。
tests/functional.suite.yml
は次のようになります。
modules:
enabled: [Db, Doctrine2, FunctionalHelper]
config:
Db:
cleanup: false
Db
モジュールは未だテスト後にdumpからデータベースの再構築を行います。populate: false
を使って、それを無効にしてください。
Dbh モジュール
PostgreSQLまたは他のネストされたトランザクションをサポートしているデータベースを使っているのでしたら、Dbh
モジュールを使用してください。アプリケーションからPDOインスタンスを取得し、テストの開始でトランザクションを開始して終了後にロールバックします。PDO接続はブートストラップファイルで定義することができます。このモジュールはDb
モジュールのseeInDatabase
メソッドとdontSeeInDatabase
メソッドを上書きします。
再構築にDb
モジュールを使用し、クリーンアップにDhp
モジュールを行うには、次のように設定してください。
modules:
enabled: [Db, Dbh, FunctionalHelper]
config:
Db:
cleanup: false
Dbh
モジュールはDb
モジュールの後に来なければいけないことに注意してください。これによってDbh
モジュールはアクションを上書きできるようになります。
フィクスチャ
フィクスチャはテストで使用できるサンプルデータです。このデータは生成されるか、サンプルデータベースから取得されます。フィクスチャは別のPHPファイルで定義され、テストにロードできます。
受け入れテストと機能テストのフィクスチャ
tests/functional
内にfixtures.php
ファイルを作り、テストで使用するデータをデータベースからロードしてみましょう。
<?php
// サンプルデータベースからユーザを取得します
// Dbモジュールを使用します
$john = User::findOneBy('name', 'john');
?>
受け入れテストと機能テストのサンプルでのフィクスチャの使用方法です:
<?php
require 'fixtures.php';
$I = new FunctionalTester($scenario);
$I->amLoggedAs($john);
$I->see('Welcome, John');
?>
また、Faker ライブラリを使ってブートストラップファイル内にテストデータを作成することもできます。
テストごとのフィクスチャ
もしあなたが1つのテストに対して特別なデータベースレコードを作りたいのなら、Db
モジュールのhaveInDatabase
メソッドを使用できます。
<?php
$I = new FunctionalTester($scenario);
$I->haveInDatabase('posts', array('title' => 'Top 10 Testing Frameworks', 'body' => '1. Codeception'));
$I->amOnPage('/posts');
$I->see('Top 10 Testing Frameworks');
?>
haveInDatabase
は、与えられた値の行を新しくデータベースに挿入します。追加されたレコードはすべてテスト終了後に削除されます。似たようにMongoDB
モジュールでは、haveInCollection
メソッドが存在します。
まとめ
Codeceptionは、データを取り扱う開発者を見捨てたりしません。データベースを構築したりクリーンアップするためのツールはDb
モジュール内にバンドルされています。テストでサンプルデータを操作するには、ブートストラップファイル内で定義されるフィクスチャを使用してください。