Prev Next

第20章 PHPUnit の実装

PHPUnit の実装はちょっと見慣れないものでしょう。 通常のアプリケーションでは保守しづらくなるようなテクニックを使用したりしています。 PHPUnit がテストを実行する仕組みを知っておくと、 あなたがテストを書く際に役立つこともあるでしょう。

個々のテストは PHPUnit_Framework_Test のオブジェクトで表され、テストを実行するには PHPUnit_Framework_TestResult のオブジェクトが必要です。PHPUnit_Framework_TestResult オブジェクトが PHPUnit_Framework_Test オブジェクトの run() メソッドに渡され、 このメソッドが実際のテストメソッドを実行します。そこで発生した例外を PHPUnit_Framework_TestResult オブジェクトに報告します。 これは、Smalltalk の世界では Collecting Parameter と呼ばれているお決まりのパターンです。複数のメソッドの結果 (ここでは、各テストを起動する run() メソッドの結果) を一箇所にまとめたい場合は、メソッドにパラメータを追加すればそれが結果を集めてくれるのです。 Erich Gamma と Kent Beck の "JUnit: A Cook's Tour" [GammaBeck1999] や Kent Beck の "Smalltalk Best Practice Patterns" [Beck1997] [Beck1997-ja] を参照ください。

PHPUnit がテストを実行するしくみをより深く探るため、 例 20.1 のようなテストクラスを考えてみましょう。

例 20.1: The EmptyTest class

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

class EmptyTest extends PHPUnit_Framework_TestCase
{
private $emptyArray = array();

public function testSize()
{
$this->assertEquals(0, sizeof($this->emptyArray));
}

public function testIsEmpty()
{
$this->assertTrue(empty($this->emptyArray));
}
}
?>

テストが実行されるときに PHPUnit がまず行うのは、テストクラスを PHPUnit_Framework_Test オブジェクトに変換することです。 ここでは、PHPUnit_Framework_TestSuite には 図 20.1 に見られるように 2 つの EmptyTest インスタンスが含まれます。

図20.1 実行しようとしているテスト

実行しようとしているテスト

PHPUnit_Framework_TestSuite の実行時には、各 EmptyTest が順に実行されます。その中では各自の setUp() メソッドが実行され、各テストについて 図 20.2 に見られるような新しい $emptyArray を作成します。 こうすることで、あるテストが配列を変更したとしても それが他のテストに影響を及ぼさないようになります。 仮にグローバル変数やスーパーグローバル変数 ($GLOBALS など) を変更したとしても、それは他のテストには影響を及ぼしません。

注記

グローバル変数やスーパーグローバル変数の保存と復元には serialize() および unserialize() を使用しています。 PHP 自体が提供する一部のクラス、たとえば PDO などのオブジェクトはシリアライズできないので、 このようなオブジェクトが $GLOBALS 配列に格納されている場合は保存に失敗します。

グローバル変数やスーパーグローバル変数の保存と復元を無効にするには、 このようにします。

class MyTest extends PHPUnit_Framework_TestCase
{
    protected $backupGlobals = FALSE;

    // ...
}

$backupGlobals 属性をたとえば setUp() メソッドの中で設定したとしても、 なんの効果もないことに注意しましょう。

図20.2 テストを実行した後の fixture の状態

テストを実行した後の fixture の状態

つまり、テストが実行される際には、ひとつのテストケースクラスが 2 段階のオブジェクトツリーになるということです。各テストは setUp() で作成された自分自身のコピーの上で実行され、テストは完全に独立して実行されます。

PHPUnit は、リフレクションを使用してインスタンス変数 $name からメソッド名を取得し、そのテストメソッドを実行します。これは、Smalltalk の世界では Pluggable Selector と呼ばれているお決まりのパターンです。 Pluggable Selector を使用することでテストをよりシンプルに書くことができますが、 その代わりコードを見ただけではどのメソッドが実行されるのかがわからなくなります。 実行されるメソッドを知るには、実行時のデータの値を調べなければならないのです。

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. 著作権