2017-06-20 13 views
3

現在、PHPUnitフレームワークでデータベースをテストする方法を学習しており、テストで実際のデータベースに接続したくないという問題がありました。これは、別のコンピュータでテストを実行すると、このコンピュータに同じデータベースがない可能性があるためです。PHPUnitのメモリ内SQLITEデータベースのデータを模倣する

私は\PHPUnit\DbUnit\TestCaseTrait形質を実施し、次の方法の設定:

/** 
* Returns the test database connection. 
* 
* @return \PHPUnit\DbUnit\Database\Connection 
*/ 
protected function getConnection() 
{ 
    $pdo = new PDO('sqlite::memory:'); 
    return $this->createDefaultDBConnection($pdo, ':memory:'); 
} 

/** 
* Returns the test dataset. 
* 
* @return \PHPUnit\DbUnit\DataSet\IDataSet 
*/ 
protected function getDataSet() 
{ 
    return $this->createXMLDataSet(dirname(__FILE__) . '/test-dataset.xml'); 
} 

データセットファイルが存在し、適切に発見されました。

私のテストのsetUpメソッドでは、オブジェクトの変数を\PDOインスタンスに設定しました。

/** 
* @var PDO $databaseServerConnection 
*/ 
private $databaseServerConnection; 

public function setUp() 
{ 
    $this->databaseServerConnection = $this->getConnection()->getConnection(); 
} 

私は今​​方法でデータセットファイルから来たデータとそのPDO接続を使用することができ期待。私自身の試みのために

、私は次のコードでそれらを比較してみました:これをデバッグする場合

# Specify the tables we want to have in our connection dataset 
$tables = ['users']; 

# Create the dataset in the connection with the tables 
$dataset = $this->getConnection()->createDataSet($tables); 

# Query all results from the user table in the connection 
$queryTable = $this->getConnection()->createQueryTable(
    'users', 'SELECT * FROM users' 
); 

# Get the raw table data from the dataset file 
$expectedTable = $this->getDataSet()->getTable('users'); 

# Check if theyre equal 
$this->assertTablesEqual($queryTable, $expectedTable); 

、私は$dataset内部$tables配列変数がちょうど空であることに気づきました。ここでは、変数$datasetvar_dumpです。

class PHPUnit\DbUnit\Database\FilteredDataSet#18 (3) { 
    protected $tableNames => 
    array(1) { 
    [0] => 
    string(5) "users" 
    } 
    protected $tables => 
    array(0) { 
    } 
    protected $databaseConnection => 
    class PHPUnit\DbUnit\Database\DefaultConnection#16 (2) { 
    protected $connection => 
    class PDO#15 (0) { 
    } 
    protected $metaData => 
    class PHPUnit\DbUnit\Database\Metadata\Sqlite#17 (6) { 
     protected $columns => 
     array(0) { 
     ... 
     } 
     protected $keys => 
     array(0) { 
     ... 
     } 
     protected $truncateCommand => 
     string(11) "DELETE FROM" 
     protected $pdo => 
     class PDO#15 (0) { 
     ... 
     } 
     protected $schema => 
     string(8) ":memory:" 
     protected $schemaObjectQuoteChar => 
     string(1) """ 
    } 
    } 
} 

また$queryTable変数内部$data配列nullあります。ここに彼$queryTablevar_dump変数。

class PHPUnit\DbUnit\DataSet\QueryTable#22 (6) { 
    protected $query => 
    string(19) "SELECT * FROM users" 
    protected $databaseConnection => 
    class PHPUnit\DbUnit\Database\DefaultConnection#20 (2) { 
    protected $connection => 
    class PDO#19 (0) { 
    } 
    protected $metaData => 
    class PHPUnit\DbUnit\Database\Metadata\Sqlite#21 (6) { 
     protected $columns => 
     array(0) { 
     ... 
     } 
     protected $keys => 
     array(0) { 
     ... 
     } 
     protected $truncateCommand => 
     string(11) "DELETE FROM" 
     protected $pdo => 
     class PDO#19 (0) { 
     ... 
     } 
     protected $schema => 
     string(8) ":memory:" 
     protected $schemaObjectQuoteChar => 
     string(1) """ 
    } 
    } 
    protected $tableName => 
    string(5) "users" 
    protected $tableMetaData => 
    NULL 
    protected $data => 
    NULL 
    private $other => 
    NULL 
} 

この$expectedTable変数内部$data配列は、データセットファイルで作成したデータの完全である一方で。

class PHPUnit\DbUnit\DataSet\DefaultTable#30 (3) { 
    protected $tableMetaData => 
    class PHPUnit\DbUnit\DataSet\DefaultTableMetadata#34 (3) { 
    protected $columns => 
    array(3) { 
     [0] => 
     string(2) "id" 
     [1] => 
     string(4) "name" 
     [2] => 
     string(5) "email" 
    } 
    protected $primaryKeys => 
    array(0) { 
    } 
    protected $tableName => 
    string(5) "users" 
    } 
    protected $data => 
    array(4) { 
    [0] => 
    array(3) { 
     'id' => 
     string(1) "1" 
     'name' => 
     string(3) "test1" 
     'email' => 
     string(9) "[email protected]" 
    } 
    [1] => 
    array(3) { 
     'id' => 
     string(1) "2" 
     'name' => 
     string(3) "test2" 
     'email' => 
     string(9) "[email protected]" 
    } 
    [2] => 
    array(3) { 
     'id' => 
     string(1) "3" 
     'name' => 
     string(6) "test3" 
     'email' => 
     string(12) "[email protected]" 
    } 
    [3] => 
    array(3) { 
     'id' => 
     string(1) "4" 
     'name' => 
     string(4) "test4" 
     'email' => 
     string(10) "[email protected]" 
    } 
    } 
    private $other => 
    NULL 
} 

私もその中の値を使用してテーブルを作成するために、getConnection()メソッド内のPDO接続オブジェクト上で2つのクエリを実行しようとしました:

protected function getConnection() 
{ 
    $pdo = new PDO('sqlite::memory:'); 
    $pdo->exec("CREATE TABLE users (id PRIMARY KEY, name VARCHAR(50), email VARCHAR(50))"); 
    $pdo->exec("INSERT INTO users (id, name, email) VALUES (20, 'Bas', '[email protected]')"); 

    return $this->createDefaultDBConnection($pdo, ':memory:'); 
} 

それはいずれかが私の存在しないことを来るどのように私の接続で利用可能なデータのデータセットファイルからデータをここにインポートしてテストをパスするにはどうしたらいいですか?

また、これを行うのは良い方法ですか?

答えて

3

私があなたの中でsetUp()を見る限り、\PHPUnit\DbUnit\TestCaseTraitsetting up and tearing downを担当するロジックを含む\PHPUnit\DbUnit\TestCaseTraitのオーバーライドを上書きします。:あなたがテストケースで異なるsetUp年代を持っている必要がある場合は、ドキュメントにdescribedとして、独自の基本クラスを作成し、それから、あなたのTestCaseのを拡張し、子供からparent::setUp()を呼び出すために良いアイデアかもしれません

UPDATEをテストケース

The Database, tables, sequences, triggers and views have to be created before you run the test suite.

これはhereから取得され、そこにはさらに役立つヒントがあります。

基本的には、テストを実行する前に、テスト対象のdb関連コードが扱い、依存するすべてのテーブル、カラム、インデックス、制約などが配置されている必要があります。実行前にそのdb内のコンテンツは問題ではなく、TestCaseのデータセットに含まれるすべてのテーブルは切り捨てられ、そのデータセットのデータで埋められます。

UPDATE 2:

通常のゲートウェイのいくつかの種類を介して実行されたDBへのアクセス(免責事項以下は私の個人的な好みです)。そして、それらは私が実装する最後のものです(少なくともパッケージスコープで)。それは、私がこれらのゲートウェイを始めるときにデータベースに格納する必要のあるデータについて本当の知識を持つ機会を与えてくれます。だから、いくつかのゲートウェイにいくつかのTestCaseを書き始めるとき、私は管理ツール(通常はphpMyAdminのようなGUI)に行き、ゲートウェイが扱うデータを格納するために必要なテーブル(テーブル)とカラムを作成するだけです。次に、テストを書いて、それらを実行することは、テーブルの変更間で、どのようにフィットするかを考えます。

このようなアプローチでは、dbのすべての構造が(テストコードではなく)手動で作成され、dbで動作するコードとともに拡張されます。私はいくつかの理由でそれが便利だと思う。

まず、各TestCaseの前に構造の作成(または再作成)を管理する必要がないので、これは簡単です。特に同じテーブルで動作するテストケースが複数ある場合は特にそうです。

第2に、私は常にテストが合格するのに適したdb構造を持っています。構造に不適切な変化があれば、それが捕らえられます。また、私はいつも必要なすべてのテーブル、列、インデックス、キーなどで実際の生活のデータベースを開始するために、この適切な構造のSQLエクスポート命令を生成することができます

第三に、 db固有の問題だけを念頭に置いてデータベース上で行われます。だから私はいつも現在のテストDBを開き、それが何であるかをきれいに見ることができます。

メモ帳内のメモ。 この場合、コードで構造を作成する必要があります。ここでは、テストスイート全体または特定のテストケース(またはそのグループ)の特定の構造を持つdbを設定するという2つの明白なオプションがあります。私の場合、私は上記の理由に基づいて最初のことをします。

実装する最も簡単な方法は、ブートストラップファイルに接続して構造を作成することです。しかし、私はいくつかの時間を投資し、このようなダイナミクスを少し追加します。

<?xml version="1.0" encoding="UTF-8" ?> 
<phpunit> 
    <php> 
     <var name="MAKE_IN_MEMORY_DB" value="yes" /> 
    </php> 
</phpunit> 

と:

abstract class AbstractDbTestCase extends \PHPUnit\DbUnit\TestCase 
{ 
    private $connection; 

    protected function getConnection() { 
     if($this->connection === NULL){ 
      $this->connection = $this->createConnection(); 
     } 
     return $this->connection; 
    } 

    private function createConnection(){ 
     if($GLOBALS['MAKE_IN_MEMORY_DB'] == 'yes'){ 
      return $this->createInMemory(); 
     } 
     else { 
      return $this->createRealDbConnection(); 
     } 
    } 

    private function createInMemory(){ 
     // create connection and set up db; 
    } 

    private function createRealDbConnection(){ 
     // create connection using some data from phpunit.xml 
    } 
} 

テストをより環境の制約から切り離さになるだろう - のみ設定調整が必要になるがテストを実行する。実際には私はさらに多くのことを行い、SQL文を含むファイルを使用してcreateInMemory()をロードします(余分な作業が必要ですが、それは価値があると思います)。

+1

残念ながら動作しませんでしたこと...私はエラー 'COMPOSITE [TRUNCATE]操作がクエリに失敗しました: 引数を使用して "ユーザー" 。DELETE FROM:配列 ( ) [SQLSTATE [HY000]:一般的なエラー: 1 no such table:users] ' – Bas

+0

ありがとうございました!これらのテーブルをインポートするのにベストプラクティスは何でしょうか? 'getConnection'メソッドの中で抽象データベースのテストケースから拡張された' setUp'メソッドの中に? – Bas

+0

私はヘルプを訴えますが、メモリ内のデータベースではないときにそのようなデータベースをセットアップすることはできませんか?私は混乱しています。 – Bas

関連する問題