Prev Next

第10章 スタブ

いろいろな要因で失敗する可能性があるテストよりも、 単一の事項のみをテストするテストのほうが情報を得やすくなります。では、 できるだけ外部からの影響を受けないようなテストを作成するには どうすればいいのでしょうか? 単純なことです。 高価で面倒で頼りなくて遅くて複雑なリソースを、シンプルな PHP オブジェクトで作成したスタブに置き換えればいいのです。たとえば、 複雑な計算をする代わりに単に定数を返すだけのものを、テスト用に作成すればいいのです。

スタブを使用すると、高価な外部リソースを使用することによる問題を解決できます。 たとえばデータベース接続のようなリソースをテスト間で共有するには PHPUnit2_Extensions_TestSetup デコレータを使用すればいいのですが、 テストの目的を考えると、データベースを使用せずにすむのならばそのほうがずっとよいでしょう。

スタブを使用するもうひとつの利点は、よりよい設計になることです。 あちこちで使用されているリソースを単一の窓口 (façade : ファサード) 経由でアクセスするようにすることで、 それを簡単にスタブに置き換えられるようになります。例えば、 データベースへのアクセスのコードをそこらじゅうにちりばめるのではなく、 その代わりに IDatabase インターフェイスを実装した単一の Database オブジェクトを使用するようにします。すると、 IDatabase を実装したスタブを作成することで、 それをテストに使用できるようになるのです。同時に、 テストを行う際にスタブデータベースを使用するか 本物のデータベースを使用するかを選択できるようになります。 つまり開発時にはローカル環境でテストし、 統合テスト時には実際のデータベースでテストするといったことができるようになるのです。

スタブ化しなければならない機能は、たいてい同一オブジェクト内で密結合しています。 この機能ををひとつの結合したインターフェイスにまとめることで、 システムのそれ以外の部分との結合を緩やかにすることができます。

自己シャント

オブジェクトが正しくコールされたかどうかを確かめなければならないこともあるでしょう。 コールされるオブジェクトの完全なスタブを作ることはできますが、 正確な結果を返しているかどうかを確かめるのは不便です。もっと簡単な方法は、 自己シャント (Self Shunt) パターンを使用して、 テストケース自身をスタブとして使用することです。自己シャントというのは医学用語で、 薬を注入する場所を確保するため、 チューブを挿入して動脈からとった血液を静脈にもどすことを意味します。

ここに例を示します。別のオブジェクトを観察 (observe) しているオブジェクト上で、 正しいメソッドがコールされたかどうかをテストしたいとします。まず、 Observer を実装したテストケースクラスを作成します。

class ObserverTest extends PHPUnit2_Framework_TestCase implements Observer {
}

次に、Observer のメソッドである update() を実装します。そして、観察対象のオブジェクトである Subject の状態が変化した場合にそのメソッドが正しくコールされるかどうかを調べます。

public $wasCalled = FALSE;

public function update(Subject $subject) {
    $this->wasCalled = TRUE;
}

さあ、それではテストを書いてみましょう。まず新しい Subject オブジェクトを作成し、テストオブジェクトをオブザーバとしてアタッチします。 Subject の状態が変化すると (例えば doSomething() メソッドがコールされるなど)、Subject オブジェクトは全オブザーバの update() メソッドをコールしなければなりません。ここではインスタンス変数 $wasCalled を使用し、update() の中でその値を設定します。これにより、Subject オブジェクトが期待通りの動作をしているかどうかを確かめます。

public function testUpdate() {
    $subject = new Subject;
    $subject->attach($this);
    $subject->doSomething();

    $this->assertTrue($this->wasCalled);
}

グローバルなインスタンスではなく、新しい Subject オブジェクトを作成したことに注意してください。スタブを利用する際には、 このような設計をお勧めします。こうすると、 オブジェクト間の結合度が緩やかになり、再利用性が高まります。

自己シャントパターンになじみのない方には、このテストはわかりにくいかもしれません。 いったいここで何が起こっているんだ? テストケース自身がオブザーバになるだって? でも、お決まりのパターンをいったん身につけてしまえば、 これらのテストは簡単に理解できるようになります。 テストの内容をつかむために必要なことは、 すべてひとつのクラスの中に含まれているのですから。

Prev Next