さまざまなテスト方法
まず、ユニットテストまたは統合テストを定義します。レイヤーの数は、1つのクラスのみをテストする可能性が高いため、ユニットテストには関係ありません。あなたがモックアウトする残り。統合テストの場合、複数のレイヤーをテストすることは避けられません。適切な単体テストがある場合は、統合テストを複雑にしすぎないようにすることがコツです。
単体テストが適切であれば、統合テストを行うときにすべての詳細をテストする必要はありません。
私たちが使用する用語は、それらはプラットフォームに少し依存していますが、ほとんどすべてのテスト/開発プラットフォームで見つけることができます:
応用例
使用するテクノロジーによって名前は異なる場合がありますが、例としてこれを使用します。
モデルProduct、ProductsController、および製品を含むHTMLテーブルを生成するインデックスビューを持つ単純なCRUDアプリケーションがある場合:
アプリケーションの最終結果は、アクティブなすべての製品のリストを含むHTMLテーブルを示しています。
単体テスト
モデル
モデルは非常に簡単にテストできます。それにはさまざまな方法があります。フィクスチャを使用します。それはあなたが「偽のデータセット」と呼ぶものだと思います。したがって、各テストを実行する前に、テーブルを作成し、元のデータを入れます。ほとんどのプラットフォームには、このためのメソッドがあります。たとえば、テストクラスでは、各テストの前に実行されるメソッドsetUp()。
次に、テストを実行します(例:testGetAllActive製品)。
したがって、テストデータベースに対して直接テストします。データソースのモックアウトは行いません。常に同じにします。これにより、たとえばデータベースの新しいバージョンでテストでき、クエリの問題が発生します。
現実の世界では、常に100%の単一の責任に従うことはできません。これをさらに良くしたい場合は、モックしたデータソースを使用できます。私たち(ORMを使用)にとっては、既存のテクノロジーをテストするような感覚です。また、テストははるかに複雑になり、クエリを実際にテストしません。そのため、このようにします。
ハードコードされたデータは、フィクスチャーに個別に保存されます。したがって、フィクスチャはcreate tableステートメントと使用するレコードの挿入を含むSQLファイルのようなものです。大量のレコードでテストする必要が実際にない限り、それらを小さく保ちます。
class ProductModel {
public function getAllActive() {
return $this->find('all', array('conditions' => array('active' => 1)));
}
}
コントローラ
コントローラーを使用してモデルをテストしたくないため、コントローラーにはさらに作業が必要です。したがって、モデルのモックを作成します。つまり、レコードのリストを返すindex()メソッドをテストします。
そこで、モデルメソッドgetAllActive()をモックアウトし、その中に固定データ(たとえば2つのレコード)を追加します。次に、コントローラーがビューに送信するデータをテストし、実際にこれらの2つのレコードを取得するかどうかを比較します。
function testProductIndexLoggedIn() {
$this->setLoggedIn();
$this->ProductsController->mock('ProductModel', 'index', function(return array(your records) ));
$result=$this->ProductsController->index();
$this->assertEquals(2, count($result['products']));
}
それで十分です。テストを難しくするため、コントローラーに機能をほとんど追加しないようにします。しかしもちろん、常にいくつかのコードが含まれています。たとえば、次のような要件をテストします。ログインしている場合にのみ、これらの2つのレコードを表示します。
そのため、コントローラーには通常1つのモックとハードコードされた小さなデータが必要です。ログインシステムの場合は、別のシステムになる可能性があります。テストでは、ヘルパーメソッドsetLoggedIn()があります。これにより、ログインありまたはログインなしのテストが簡単になります。
class ProductsController {
public function index() {
if($this->loggedIn()) {
$this->set('products', $this->ProductModel->getAllActive());
}
}
}
視聴回数
ビューのテストは困難です。最初に、繰り返すロジックを分離します。ヘルパーに入れて、それらのクラスを厳密にテストします。常に同じ出力が期待されます。たとえば、generateHtmlTableFromArray()。
次に、プロジェクト固有のビューがいくつかあります。私たちはそれらをテストしません。それらを単体テストすることは本当に望ましくありません。統合テストのためにそれらを保持します。多くのコードをビューに組み込んだため、ここでのリスクは低くなります。
これらのテストを開始する場合、ほとんどのプロジェクトでは役に立たないHTMLを変更するたびにテストを変更する必要があります。
echo $this->tableHelper->generateHtmlTableFromArray($products);
統合テスト
ここにあなたのプラットフォームによっては、それは次のようにウェブベースの可能など、ユーザーストーリー、と働くことができるセレンまたは他の同等のソリューション。
通常、フィクスチャを使用してデータベースをロードし、利用可能なデータをアサートします。完全な統合テストでは、通常、非常にグローバルな要件を使用します。そのため、製品をアクティブに設定し、製品が使用可能になるかどうかを確認します。
適切なフィールドが使用可能かどうかなど、すべてを再度テストするわけではありません。ここで、より大きな要件をテストします。コントローラーまたはビューからテストを複製したくないので。何かが本当にアプリケーションのキー/コア部分である場合、またはセキュリティ上の理由(パスワードを確認できない)である場合は、正しいことを確認するためにそれらを追加します。
ハードコードされたデータはフィクスチャに保存されます。
function testIntegrationProductIndexLoggedIn() {
$this->setLoggedIn();
$result=$this->request('products/index');
$expected='<table';
$this->assertContains($expected, $result);
// Some content from the fixture record
$expected='<td>Product 1 name</td>';
$this->assertContains($expected, $result);
}