2011-09-13 10 views
8

私のウェブサイトには高度な検索機能があります。 Pleopleはそこに行ってentitiy(例えば、車)を検索することができます。私は検索パラメータに基づいて結果の数を確認するいくつかのテストを作成しました。私はどのようなテストを書くべきかを考え、それを書いてから、テスト・データベースにデータを追加します。しかし、ここで問題が起こる。新しい値をデータベースに挿入すると、古いテストが中断します。これは、レコード数を確認しているからです...TDD:検索をテストするには?

<?php defined('SYSPATH') or die('No direct access allowed!'); 

class Search_Test extends PHPUnit_Extensions_Database_TestCase 
{ 
    /** 
    * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection 
    */ 
    public function getConnection() 
    { 
     $pdo = new PDO('mysql:dbname=db_test;host=127.0.0.1', 'root', null); 
     return $this->createDefaultDBConnection($pdo, 'db_test'); 
    } 

    /** 
    * @return PHPUnit_Extensions_Database_DataSet_IDataSet 
    */ 
    public function getDataSet() 
    { 
     $fixture = realpath(dirname(__FILE__).'/../data/fixture.xml'); 
     return $this->createXMLDataSet($fixture); 
    } 

    public function numberOfResultsDataProvider() 
    { 
     return array(
      array(1, null, null, 1), 
      array(2, null, null, 3), 
      array(3, null, null, 0), 
      array('abc', null, null, 5), 
      array(null, 1996, 2003, 3), 
      array(null, 1996, 1999, 2), 
      array(null, 2002, 2003, 1), 
      array(null, 1500, 1800, 0), 
      array(null, 2003, 2003, 1), 
      array(null, null, 2005, 4), 
      array(null, 1996, null, 4), 
      array(null, null, null, 4), 
      array(null, 2003, 1996, 0), 
      array(null, 'abc', 2003, 4), 
      array(null, '1996', '1999', 2), 
      array(2, 2003, 2005, 2), 
      array(null, null, null, 4), 
     ); 
    } 

    /** 
    * @dataProvider numberOfResultsDataProvider 
    */ 
    public function testNumberOfResults($brandId, $startYear, 
     $endYear, $numberOfResults 
    ) { 
     $search = ORM::factory('search'); 
     $search->setBrand($brandId) 
      ->setYearRange($startYear, $endYear); 
     $results = $search->results(); 
     $this->assertEquals($results->count(), $numberOfResults); 
    } 
} 
?> 

これは正常ですか?新しいテストを作成するときに古いテストを中断する必要がありますか?

テストはデータにバインドする必要がありますか?

検索条件が多すぎるため、同じフォーム(ビュー)で使用されます。各パラメータを検索するテストを作成するか、それらを一緒にテストする必要がありますか?私はもっ​​と多くのテストクラスでそれを分割すべきでしょうか?

ありがとうございました。

+1

良い質問ですが、おそらくhttp://programmers.stackexchange.comに適しています。 – Maxpm

答えて

6

データベースを含む単体テストを行う場合、テストは実際にテストするデータベースを提供する必要があります。それは、テストに関連する値だけを含む単純なデータベースです(一致する行と一致しない行など)。また、特定の時点で存在していたライブデータベースのスナップショットに対して複数のテストを構築することも妥当です。

これを達成するのに特に便利な方法の1つは、テスト専用のSqlite3データベースであり、テスト用にそのアプリケーションを使用するように設定することです。

0

新しいテストを作成するときには、でなく、でなければなりません。テストはではなく、である必要があります。特定のデータをデータベースに必要とするテストでは、そのデータをデータベースに格納する必要があります。データベースに他のデータがないことが必要な場合は、他のすべてのデータを消去する必要があります。

これはもちろん、テストを遅くするため、データアクセスレイヤをモックアウトします。

+0

これは高度な検索で、ユーザーはさまざまなパラメータを設定できます。私はそれがすべての道をテストすることは不可能だと思うが、多分いくつかのテストで私は多くのデータフィクスチャを設定する必要があります...それは正常ですか?私は何か間違っているのですか?ありがとう。 – thom

1

可能であれば、コードがデータを取り込む方法とデータベース自体の関係を切り離すべきです。単体テストはデータベースに依存してはいけません。いくつかの理由を見つけました。なぜなら、テスト全体でデータを維持し、新しいテストを作成して他の人が休憩するなどです。何とかデータアクセスポイントを偽造し、データを厳密にメモリに戻すことができれば、理想的なケースです。私はPHPでいかに簡単かはわかりませんが、データアクセスコードの周りにインタフェースを構築し、そのインタフェースを擬似/擬似的に実装することは、この目標を達成するのに役立ちます。

0

私は、それぞれのテストメソッドで独自のデータを作成してから、そのサンプルデータを引き出し、アサートし、破壊します。

私は通常、共有のaddData()メソッドを使用し、次にデータベースのクリーンアップメソッドを使用します。追加されたデータを何らかの方法で識別可能にして、クリーンアップメソッドが一般的なものになることができればうれしいことです。あなたの例では、brandIdのすべてを "test-"で始めることができ、その場合、brandIdが 'test-%'のようなすべてのレコードを検索して削除します。

1

要するに:
ライブデータベース

上でこれを行うまさかあなたがテスト用に別のデータベースを必要としています。これは実際にはデータベースのモックであるかもしれません。

次に、テストの前に、固定状態になるようにデータベースを準備する必要があります(たとえば、フィクスチャからデータをロードする、またはSQLファイルをインポートするなど)。

次に、元のデータベースの状態を変更する場合は、データベーストランザクションが最適です。

トランザクションが開始されたら、データベースで作業することができます。

テストを完了した後は、ロールバックトランザクションのみが実行され、データベースはクリーン状態になります。

ほとんどの場合、Sqliteはうまくいくが、ライブデータベースとは異なる場合があります。とにかく、異なるデータベースアダプターを持つことは非常に役に立ちます。

関連する問題