Prev Next

第6章 Fixtures

テストを記述する際にいちばん時間を食うのは、テストを開始するための事前設定と テスト終了後の後始末の処理を書くことです。この事前設定は、テストの fixture と呼ばれます。

例 4.1 では、fixture は $fixture という変数に格納された配列だけでした。 しかしたいていの場合は fixture はこれより複雑なものとなり、 それを準備するにはかなりの量のコードが必要です。本来のテストの内容が、 fixture を設定するためのコードの中に埋もれてしまうことになります。 この問題は、複数のテストで同じような fixture を設定する場合により顕著になります。 テストフレームワークの助けがなければ、 個々のテストのなかで同じような準備コードを繰り返し書くはめになってしまいます。

PHPUnit は、準備用のコードの共有をサポートしています。 各テストメソッドが実行される前に、setUp() という名前のテンプレートメソッドが実行されます。setUp() は、テスト対象のオブジェクトを生成するような処理に使用します。 テストメソッドの実行が終了すると、それが成功したか否かにかかわらず、 tearDown() という名前の別のテンプレートメソッドが実行されます。 tearDown() では、テスト対象のオブジェクトの後始末などを行います。

それでは、setUp() を使用してコードの重複を排除するように 例 4.1 を書き換えてみましょう。 まず最初にインスタンス変数 $fixture を宣言し、 メソッド内のローカル変数ではなくこちらを使用するようにします。 そして、array fixture の生成処理を setUp() メソッドに移動します。最後に、 テストメソッド内で重複しているコードを取り除き、 新しく作成したインスタンス変数を使用するようにします。つまり、 assertEquals() で使用しているローカル変数 $fixture を、$this->fixture に置き換えます。

例 6.1: setUp() を使用して Array fixture を作成する

<?php
require_once 'PHPUnit/Framework.php';

class ArrayTest extends PHPUnit_Framework_TestCase
{
protected $fixture;

protected function setUp()
{
// Array fixture を作成します。
$this->fixture = array();
}

public function testNewArrayIsEmpty()
{
// Array fixture のサイズは 0 のはずです。
$this->assertEquals(0, sizeof($this->fixture));
}

public function testArrayContainsAnElement()
{
// Array fixture に要素を追加します。
$this->fixture[] = 'Element';

// Array fixture のサイズは 1 のはずです。
$this->assertEquals(1, sizeof($this->fixture));
}
}
?>

各テストメソッドが実行されるたびに、setUp() および tearDown() が一度ずつコールされます。 「テストケース内の全テストメソッドについて一度だけコールするように したほうがよいのではないか」とお考えになるかもしれませんが、 そのようにすると各テストを互いに独立した状態にすることが難しくなります。

テストメソッドごとに setUp() および tearDown() が一度ずつ実行されるだけでなく、 テストメソッドごとに、新しいテストケースクラスのインスタンスが作成されます (第 20 章 を参照ください)。

tearDown() よりも setUp()

setUp()tearDown() は理屈上では対称的になるはずですが、実際にはそうではありません。実際には、 tearDown() を実装する必要があるのは setUp() で外部リソース (ファイルやソケットなど) を割り当てた場合のみです。もし setUp() で単に PHP オブジェクトを作成しただけの場合は、 一般には tearDown() は必要ありません。しかし、もし setUp() で大量のオブジェクトを作成した場合には、 それらの後始末をするために tearDown() で変数を unset() したくなることもあるでしょう。 テストケースオブジェクト自体のガベージコレクションにはあまり意味がありません。

バリエーション

ふたつのテストがあって、それぞれの setup がほんの少しだけ違う場合にはどうなるでしょう? このような場合は、二種類の可能性が考えられます。

  • もし setUp() の違いがごくわずかなものなら、 その違う部分を setUp() からテストメソッドのほうに移動させます。

  • setUp() の違いが大きければ、 テストケースクラスを別に分ける必要があります。それぞれのクラスには、 setup の違いを表す名前をつけます。

Fixture の共有

複数のテストの間で fixture を を共有する利点は、ほとんどありません。 しかし、設計上の問題などでどうしても fixture を共有しなければならないこともあるでしょう。

複数のテスト間で共有する意味のある fixture の例として意味のあるものといえば、 データベースとの接続でしょう。テストのたびに新しいデータベース接続を毎回作成するのではなく、 最初にログインした状態を再利用するということです。こうすることで、 テストの実行時間を短縮できます。

例 6.2 は、PHPUnit_Framework_TestSuite クラス (「スイートレベルのセットアップ」 を参照ください) のテンプレートメソッド setUp() および tearDown() を使用します。 これらを使用して、 最初のテストの前にデータベースとの接続を行い、 最後のテストが終わった後にデータベースとの接続を解除します。 PHPUnit_Framework_TestSuite オブジェクトの属性 $sharedFixture が、 PHPUnit_Framework_TestSuite および PHPUnit_Framework_TestCase オブジェクトから使用できます。

例 6.2: テストスイートの複数テスト間での fixture の共有

<?php
require_once 'PHPUnit/Framework.php';

class DatabaseTestSuite extends PHPUnit_Framework_TestSuite
{
protected function setUp()
{
$this->sharedFixture = new PDO(
'mysql:host=wopr;dbname=test',
'root',
''
);
}

protected function tearDown()
{
$this->sharedFixture = NULL;
}
}
?>

このように fixture を共有することがテストの価値を下げてしまうということを、 まだうまく伝え切れていないかもしれません。問題なのは、 各オブジェクトが疎結合になっていないという設計なのです。 複数が連携しているようなテストを作って設計上の問題から目をそらしてしまうのではなく、 きちんと設計しなおした上で、スタブ (第 11 章 を参照ください) を使用するテストを書くことをお勧めします。

Prev Next
1. 自動テスト
2. PHPUnit の目標
3. PHPUnit のインストール
4. PHPUnit 用のテストの書き方
データプロバイダ
例外のテスト
PHP のエラーのテスト
5. コマンドラインのテストランナー
6. Fixtures
tearDown() よりも setUp()
バリエーション
Fixture の共有
7. テストの構成
スイートレベルのセットアップ
8. テストケースの拡張
出力内容のテスト
パフォーマンス低下のテスト
9. データベースのテスト
データセット
Flat XML データセット
XML データセット
操作
データベースのテストのコツ
10. 不完全なテスト・テストの省略
不完全なテスト
テストの省略
11. モックオブジェクト
自己シャント
スタブ
12. テストの進め方
開発中のテスト
デバッグ中のテスト
13. テストファーストプログラミング
銀行口座の例
14. コードカバレッジ解析
カバーするメソッドの指定
コードブロックの無視
ファイルのインクルードや除外
15. テストのその他の使用法
アジャイルな文書作成
複数チームでのテスト
16. ログ出力
XML 形式
コードカバレッジ (XML)
JavaScript Object Notation (JSON)
Test Anything Protocol (TAP)
GraphViz マークアップ
テストデータベース
17. 雛形ジェネレータ
アノテーション
18. PHPUnit と Selenium
Selenium RC
PHPUnit_Extensions_SeleniumTestCase
19. 継続的インテグレーション
CruiseControl
phpUnderControl
Apache Maven
20. PHPUnit の実装
21. PHPUnit API
概要
PHPUnit_Framework_Assert
PHPUnit_Framework_Test
PHPUnit_Framework_TestCase
PHPUnit_Framework_TestSuite
PHPUnit_Framework_TestResult
パッケージの構成
22. PHPUnit の拡張
PHPUnit_Framework_TestCase のサブクラスの作成
アサートクラスの作成
PHPUnit_Extensions_TestDecorator のサブクラスの作成
PHPUnit_Framework_Test の実装
PHPUnit_Framework_TestResult のサブクラスの作成
PHPUnit_Framework_TestListener の実装
新しいテストランナーの作成
A. アサーション
B. XML 設定ファイル
テストスイート
グループ
コードカバレッジ対象のファイルの追加や除外
ログ出力
PMD ルール
PHP INI 項目やグローバル変数の設定
C. PHP 4 用の PHPUnit
D. 目次
E. 参考文献
F. 著作権