You are currently reading the 1.2 documentation. Switch to 2.2  2.1  2.0 

Unit Testing

Doctrineはユニットテストを使用するプログラムでテストされます。Wikipediaでユニットテストの記事を読むことができます。

テストを実施する

Doctrineに搭載されるテストを実施するにはライブラリフォルダだけでなくプロジェクト全体をチェックアウトする必要があります。

$ svn co http://svn.doctrine-project.org/branches/1.2 /path/to/co/doctrine

Doctrineのチェックアウトのディレクトリに移動します。

$ cd /path/to/co/doctrine

次のファイルとディレクトリが見えます。

CHANGELOG
COPYRIGHT
lib/
LICENSE
package.xml
tests/
tools/
vendor/

認識できるテストの失敗ケースが用意されるのはめったにありません。もしくはDoctrineには後のバージョンまでコミットできないバグ修正もしくは強化リクエスト用のテストケースが存在します。もしくは単に問題の修正コードが存在しないので失敗のままのテストもあります。Doctrineのそれぞれのバージョンでどれだけの数のテストの失敗ケースがあるのかメーリングリストもしくはIRCでたずねることができます。

CLI

コマンドラインでテストを実施するには、php-cliをインストールしなければなりません。

/path/to/co/doctrine/testsフォルダに移動してrun.phpスクリプトを実行します:

$ cd /path/to/co/doctrine/tests
$ php run.php

これによってすべてのユニットテストを実行しているときに進行バーが出力されます。テストが終了したとき何が成功し何が失敗したのか報告されます。

CLIには特定のテスト、テストのグループを実施するもしくはテストスィートの名前でテストをフィルタリングするためのオプションがありあす。これらのオプションを確認するために次のコマンドを実行してください。

$ php run.php -help

次のように個別のテストグループを実行できます:

$ php run.php --group data_dict

ブラウザ

doctrine/tests/run.phpに移動すればブラウザでユニットテストを実施できます。オプションは変数_GETを通して設定できます。

例:

テストの結果が環境に大きく左右されることがあることにご注意ください。例えばphp.iniapc.enable_cliディレクティブが0に設定されている場合追加テストが失敗することがあります。

テストを書く

テストスィートを書き始めるとき、TemplateTestCase.phpをコピーすることから始めます。サンプルのテストケースは次の通りです:

class Doctrine_Sample_TestCase extends Doctrine_UnitTestCase
{
    public function prepareTables()
    {
        $this->tables[] = "MyModel1";
        $this->tables[] = "MyModel2";
        parent::prepareTables();
    }

    public function prepareData()
    {
      $this->myModel = new MyModel1();
      //$this->myModel->save();
    }

    public function testInit()
    {

    }

    // This produces a failing test
    public function testTest()
    {
        $this->assertTrue($this->myModel->exists());
        $this->assertEqual(0, 1);
        $this->assertIdentical(0, '0');
        $this->assertNotEqual(1, 2);
        $this->assertTrue((5 < 1));
        $this->assertFalse((1 > 2));
    }
}

class Model1 extends Doctrine_Record
{
}

class Model2 extends Doctrine_Record
{
}

モデルの定義はテストケースファイルに直接含まれるもしくはこれらは/path/to/co/doctrine/tests/modelsに設置可能です。そうすればこれらはオートロードされます。

テストを書く作業を終えたら必ずrun.phpに次のコードを追加してください。

$test->addTestCase(new Doctrine_Sample_TestCase());

run.phpを実行するとき新しい失敗ケースが報告されます。

チケットテスト

Doctrineにおいてtracに報告される個別のチケット用のテストの失敗ケースをコミットするのが慣行になっています。/path/to/co/doctrine/tests/Ticket/フォルダで見つかるすべてのテストケースを読むことでこれらの手数とケースは自動的にrun.phpに追加されます。

CLIから新しいテストケースのチケットを作成できます:

$ php run.php --ticket 9999

チケット番号9999がまだ存在しない場合空白のテストケースクラスが/path/to/co/doctrine/tests/Ticket/9999TestCase.phpに生成されます。

class Doctrine_Ticket_9999_TestCase extends Doctrine_UnitTestCase
{
}

テスト用のメソッド

Equalをアサートする

// ...
    public function test1Equals1()
    {
        $this->assertEqual(1, 1);
    }
// ...

Not Equalをアサートする

// ...
    public function test1DoesNotEqual2()
    {
        $this->assertNotEqual(1, 2);
    }
// ...

Identicalをアサートする

ロジックがより厳密で2つの値の比較に===を使用すること以外assertIdentical()メソッドはassertEqual()と同じです。

// ...
    public function testAssertIdentical()
    {
        $this->assertIdentical(1, '1');
    }
// ...

1番目の引数の数字の1がPHPの整数型としてキャストされるのに対して2番目の引数の数字の1はPHPの文字列型としてキャストされるので明らかに失敗します。

Trueをアサートする

// ...
    public function testAssertTrue()
    {
        $this->assertTrue(5 > 2);
    }
// ...

Falseをアサートする

// ...
    public function testAssertFalse()
    {
        $this->assertFalse(5 < 2);
    }
// ...

モックドライバ

Doctrineはsqlite以外のすべてのドライバ用のモックドライバを使用します。次のコードスニペットはモックドライバの使い方を示します:

class Doctrine_Sample_TestCase extends Doctrine_UnitTestCase
{
    public function testInit()
    {
        $this->dbh = new Doctrine_Adapter_Mock('oracle');
        $this->conn = Doctrine_Manager::getInstance()->openConnection($this->dbh);
    }
}

クエリを実行するときこれらは本当のデータベースに対して実行されません。代わりにこれらは配列に収集され実行されたクエリとそれらに対するテストのアサーションを分析できます。

class Doctrine_Sample_TestCase extends Doctrine_UnitTestCase
{
    // ...

    public function testMockDriver()
    {
        $user = new User();
        $user->username = 'jwage';
        $user->password = 'changeme';
        $user->save();

        $sql = $this->dbh->getAll();

        // 探しているクエリを見つけるためにSQL配列を出力する
        // print_r($sql);

        $this->assertEqual($sql[0], 'INSERT INTO user (username, password) VALUES (?, ?)');
    }
}

テストクラスのガイドライン

すべてのクラスはTestCaseと同等のものを少なくとも1つ持ちDoctrine_UnitTestCaseを継承します。テストクラスはクラスもしくはクラスのアスペクトを参照し、それに応じて命名されます。

例:

  • Doctrine_Record_TestCaseDoctrine_Recordクラスを指し示すので良い名前です。
  • Doctrine_Record_State_TestCaseDoctrine_Recordクラスの状態を指し示すのでこれも良い名前です。
  • Doctrine_PrimaryKey_TestCaseは一般的すぎるので悪い名前です。

テストメソッドのガイドライン

メソッドはアジャイルなドキュメントをサポートし何が失敗したのか明確にわかるように名付けられます。これらはテストするシステムの情報も提供します。

例えばメソッドのテスト名としてDoctrine_Export_Pgsql_TestCase::testCreateTableSupportsAutoincPks()は良い名前です。

テストメソッドの名前は長くなる可能性がありますが、メソッドの内容は長くならないようにすべきです。複数のアサート呼び出しが必要なら、メソッドを複数のより小さなメソッドに分割します。ロープもしくは関数の中にアサーションがあってはなりません。

共通の命名規約として使われるTestCase::test[methodName]はDoctrineではされません。ですのでこのケースではDoctrine_Export_Pgsql_TestCase::testCreateTable()は許可されません!

まとめ

Doctrineのようなソフトウェアのピースにとってユニットテストは非常に重要です。これ無しでは、変更によって既存の作業ユースケースに悪影響があるのかを知るのは不可能です。ユニットテストのコレクションによって変更が既存の機能を壊さないことを確認できます。

次にパフォーマンスを改善する方法を学ぶために移動します。


Questions and Feedback

If you find a problem with the documentation or have a suggestion, please register and open a ticket.

If you need support or have a technical question, you can post to the user mailing-list.