たいていの場合は、PHPUnit の API は単純なものです。単に
PHPUnit2_Framework_TestCase を継承したテストケースを作成し、
assertTrue() あるいは assertEquals()
をコールすればよいのです。しかし、PHPUnit をより深く知りたい方のために、
ここではすべてのクラスおよび公開メソッドを説明します。
ほとんどの場合、PHPUnit を使用する際には以下の 5 つのクラスやインターフェイスに出会うことになるでしょう。
PHPUnit2_Framework_Assert実際の値が想定した値どおりかどうかを調べるための静的メソッドを集めたもの。
PHPUnit2_Framework_Testテストケースとして動作するすべてのオブジェクトのインターフェイス。
PHPUnit2_Framework_TestCaseひとつのテスト。
PHPUnit2_Framework_TestSuiteテストの集まり。
PHPUnit2_Framework_TestResultひとつあるいは複数のテストの実行結果をまとめたもの。
PHPUnit の、5 つの基本クラス/インターフェイスである
PHPUnit2_Framework_Assert、
PHPUnit2_Framework_Test、
PHPUnit2_Framework_TestCase、
PHPUnit2_Framework_TestSuite および
PHPUnit2_Framework_TestResult の関係を
図14.1「PHPUnit の 5 つの基本クラス/インターフェイス」
に示します。
PHPUnit 用に書かれたテストケースのほとんどは、間接的に
PHPUnit2_Framework_Assert
を継承しています。ここには、
値を自動的にチェックして矛盾を報告するためのメソッドが含まれています。
これらのメソッドは静的に宣言されているので、
あなたが作成したメソッドの中で「規約による設計」方式のアサーションを使用し、
PHPUnit に結果を報告させることができます
(例14.1「「規約による設計」方式のアサーション」 を参照ください)。
例14.1 「規約による設計」方式のアサーション
<?php
require_once 'PHPUnit2/Framework/Assert.php';
class Sample {
public function aSampleMethod($object) {
PHPUnit2_Framework_Assert::assertNotNull($object);
}
}
$sample = new Sample;
$sample->aSampleMethod(NULL);
?>
Fatal error: Uncaught exception 'PHPUnit2_Framework_AssertionFailedError' with message 'expected: <NOT NULL> but was: <NULL>'
しかし、ほとんどの場合はこれらのアサーションはテストの中で行います。
各アサーションメソッドには 2 種類の方式があります。 エラー時に表示されるメッセージをパラメータとして指定する方法としない方法です。 オプションで指定したメッセージは、通常はテストが失敗したことが報告される場面で 表示されます。これにより、デバッグが楽になります。
例14.2 メッセージつきのアサーション
<?php
require_once 'PHPUnit2/Framework/TestCase.php';
class MessageTest extends PHPUnit2_Framework_TestCase {
public function testMessage() {
$this->assertTrue(FALSE, 'これは独自のメッセージです。');
}
}
?>
以下の例は、
例14.2「メッセージつきのアサーション」 のテスト
testMessage()
でメッセージつきのアサーションを使用した場合の出力結果です。
phpunit MessageTest.php
PHPUnit 2.3.0 by Sebastian Bergmann.
F
Time: 0.102507
There was 1 failure:
1) testMessage(MessageTest)
これは独自のメッセージです。
FAILURES!!!
Tests run: 1, Failures: 1, Errors: 0, Incomplete Tests: 0.表14.1「アサーション」 に、すべてのアサーションをまとめます。
表14.1 アサーション
| アサーション | 意味 |
|---|---|
void assertTrue(bool $condition) | $condition が FALSE の場合にエラーを報告します。 |
void assertTrue(bool $condition, string $message) | $condition が FALSE の場合にエラー $message を報告します。 |
void assertFalse(bool $condition) | $condition が TRUE の場合にエラーを報告します。 |
void assertFalse(bool $condition, string $message) | $condition が TRUE の場合にエラー $message を報告します。 |
void assertNull(mixed $variable) | $variable が NULL でないときにエラーを報告します。 |
void assertNull(mixed $variable, string $message) | $variable が NULL でないときにエラー $message を報告します。 |
void assertNotNull(mixed $variable) | $variable が NULL の場合にエラーを報告します。 |
void assertNotNull(mixed $variable, string $message) | $variable が NULL の場合にエラー $message を報告します。 |
void assertSame(object $expected, object $actual) | 2 つの変数 $expected と $actual が同じオブジェクトを参照していない場合にエラーを報告します。 |
void assertSame(object $expected, object $actual, string $message) | 2 つの変数 $expected と $actual が同じオブジェクトを参照していない場合にエラー $message を報告します。 |
void assertSame(mixed $expected, mixed $actual) | 2 つの変数 $expected と $actual が同じ型・同じ値でない場合にエラーを報告します。 |
void assertSame(mixed $expected, mixed $actual, string $message) | 2 つの変数 $expected と $actual が同じ型・同じ値でない場合にエラー $message を報告します。 |
void assertNotSame(object $expected, object $actual) | 2 つの変数 $expected と $actual が同じオブジェクトを参照している場合にエラーを報告します。 |
void assertNotSame(object $expected, object $actual, string $message) | 2 つの変数 $expected と $actual が同じオブジェクトを参照している場合にエラー $message を報告します。 |
void assertNotSame(mixed $expected, mixed $actual) | 2 つの変数 $expected と $actual が同じ型・同じ値である場合にエラーを報告します。 |
void assertNotSame(mixed $expected, mixed $actual, string $message) | 2 つの変数 $expected と $actual が同じ型・同じ値である場合にエラー $message を報告します。 |
void assertEquals(array $expected, array $actual) | 2 つの配列 $expected と $actual が等しくない場合にエラーを報告します。 |
void assertEquals(array $expected, array $actual, string $message) | 2 つの配列 $expected と $actual が等しくない場合にエラー $message を報告します。 |
void assertNotEquals(array $expected, array $actual) | 2 つの配列 $expected と $actual が等しい場合にエラーを報告します。 |
void assertNotEquals(array $expected, array $actual, string $message) | 2 つの配列 $expected と $actual が等しい場合にエラー $message を報告します。 |
void assertEquals(float $expected, float $actual, '', float $delta = 0) | 2 つの float 値 $expected と $actual の誤差が $delta より大きい場合にエラーを報告します。 |
void assertEquals(float $expected, float $actual, string $message, float $delta = 0) | 2 つの float 値 $expected と $actual の誤差が $delta より大きい場合にエラー $message を報告します。 |
void assertNotEquals(float $expected, float $actual, '', float $delta = 0) | 2 つの float 値 $expected と $actual の誤差が $delta 以下のにエラーを報告します。 |
void assertNotEquals(float $expected, float $actual, string $message, float $delta = 0) | 2 つの float 値 $expected と $actual の誤差が $delta 以下の場合にエラー $message を報告します。 |
void assertEquals(string $expected, string $actual) | 2 つの文字列 $expected と $actual が等しくない場合にエラーを報告します。エラーは、2 つの文字列の差分で報告されます。 |
void assertEquals(string $expected, string $actual, string $message) | 2 つの文字列 $expected と $actual が等しくない場合にエラー $message を報告します。エラーは、2 つの文字列の差分で報告されます。 |
void assertNotEquals(string $expected, string $actual) | 2 つの文字列 $expected と $actual が等しい場合にエラーを報告します。 |
void assertNotEquals(string $expected, string $actual, string $message) | 2 つの文字列 $expected と $actual が等しい場合にエラー $message を報告します。 |
void assertEquals(mixed $expected, mixed $actual) | 2 つの変数 $expected と $actual が等しくない場合にエラーを報告します。 |
void assertEquals(mixed $expected, mixed $actual, string $message) | 2 つの変数 $expected と $actual が等しくない場合にエラー $message を報告します。 |
void assertNotEquals(mixed $expected, mixed $actual) | 2 つの変数 $expected と $actual が等しい場合にエラーを報告します。 |
void assertNotEquals(mixed $expected, mixed $actual, string $message) | 2 つの変数 $expected と $actual が等しい場合にエラー $message を報告します。 |
void assertContains(mixed $needle, array $haystack) | $needle が $haystack の要素でない場合にエラーを報告します。 |
void assertContains(mixed $needle, array $haystack, string $message) | $needle が $haystack の要素でない場合にエラー $message を報告します。 |
void assertNotContains(mixed $needle, array $haystack) | $needle が $haystack の要素である場合にエラーを報告します。 |
void assertNotContains(mixed $needle, array $haystack, string $message) | $needle が $haystack の要素である場合にエラー $message を報告します。 |
void assertContains(mixed $needle, Iterator $haystack) | $needle が $haystack の要素でない場合にエラーを報告します。 |
void assertContains(mixed $needle, Iterator $haystack, string $message) | $needle が $haystack の要素でない場合にエラー $message を報告します。 |
void assertNotContains(mixed $needle, Iterator $haystack) | $needle が $haystack の要素である場合にエラーを報告します。 |
void assertNotContains(mixed $needle, Iterator $haystack, string $message) | $needle が $haystack の要素である場合にエラー $message を報告します。 |
void assertRegExp(string $pattern, string $string) | $string が正規表現 $pattern にマッチしない場合にエラーを報告します。 |
void assertRegExp(string $pattern, string $string, string $message) | $string が正規表現 $pattern にマッチしない場合にエラー $message を報告します。 |
void assertNotRegExp(string $pattern, string $string) | $string が正規表現 $pattern にマッチする場合にエラーを報告します。 |
void assertNotRegExp(string $pattern, string $string, string $message) | $string が正規表現 $pattern にマッチする場合にエラー $message を報告します。 |
void assertType(string $expected, mixed $actual) | 変数 $actual の型が $expected でない場合にエラーを報告します。 |
void assertType(string $expected, mixed $actual, string $message) | 変数 $actual の型が $expected でない場合にエラー $messageを報告します。 |
void assertNotType(string $expected, mixed $actual) | 変数 $actual の型が $expected である場合にエラーを報告します。 |
void assertNotType(string $expected, mixed $actual, string $message) | 変数 $actual の型が $expected である場合にエラー $messageを報告します。 |
これら以外に、プロジェクトで使用している
オブジェクト固有のアサーションが必要になることもあるでしょう。独自の
Assert クラスを作成し、
そこに独自のアサーションを含めてテストに使用することができます。
アサーションに失敗すると、ボトルネックメソッド
fail(string $message) がコールされ、これは
PHPUnit2_Framework_AssertionFailedError をスローします。
このメソッドにもパラメータなしのものがあります。テストでエラーが発生した際に、
fail() を明示的にコールします。
例外が発生することが期待されるテストなどがその例になります。
表14.2「ボトルネックメソッド」
に、PHPUnit のボトルネックメソッドをまとめます。
PHPUnit2_Framework_Test は、
テストとして働くすべてのオブジェクトが使用する、
一般的なインターフェイスです。これを実装したオブジェクトは、
ひとつあるいは複数のテストを表すことになります。
表14.3「実装することになるメソッド」
に示す 2 つのメソッドが定義されています。
表14.3 実装することになるメソッド
| メソッド | 意味 |
|---|---|
int countTestCases() | テストの数を返します。 |
void run(PHPUnit2_Framework_TestResult $result) | テストを実行し、結果を $result で報告します。 |
PHPUnit2_Framework_Test の実装クラスとして有名なのは、
PHPUnit2_Framework_TestCase および
PHPUnit2_Framework_TestSuite の 2 つです。
PHPUnit2_Framework_Test を実装したクラスを独自に作成することも可能です。
このインターフェイスはあえて小規模に設計されているので、実装するのは簡単でしょう。
テストケースクラスは PHPUnit2_Framework_TestCase
クラスを継承して作成します。たいていの場合は、
テストスイートから自動的にテストを実行させることになるでしょう。
この場合、(規約により) 各テストは test*
という名前のメソッドにしておかなければなりません。
PHPUnit2_Framework_TestCase は
PHPUnit2_Framework_Test::countTestCases() を実装しており、
これは常に 1 を返します。このクラスで実装されている
PHPUnit2_Framework_Test::run(PHPUnit2_Framework_TestResult $result)
は、まず setUp() を実行し、テストメソッドを実行し、
それから tearDown() を実行し、その結果を
PHPUnit2_Framework_TestResult に報告します。
PHPUnit2_Framework_TestCase によって実装されている外部プロトコルを
表14.4「TestCase の外部プロトコル」 にまとめます。
表14.4 TestCase の外部プロトコル
| メソッド | 意味 |
|---|---|
__construct() | テストケースを作成します。 |
__construct(string $name) | 指定した名前のテストケースを作成します。この名前はテストケースを表示する際に使用されます。また、リフレクションで取得するテストメソッドの名前としても使用されます。 |
string getName() | テストケースの名前を返します。 |
void setName($name) | テストケースの名前を設定します。 |
PHPUnit2_Framework_TestResult run(PHPUnit2_Framework_TestResult $result) | テストケースを実行し、結果を $result に格納するための便利なメソッドです。 |
void runTest() | リフレクションによってテストメソッドを実行されたくない場合に、テストメソッドをオーバーライドします。 |
このクラスには 2 つのテンプレートメソッド setUp()
および tearDown() が存在します。これをオーバーライドすると、
実行しようとしているテストに関する前処理や後始末を行うことができます。
表14.5「テンプレートメソッド」
にこれらのメソッドをまとめます。
表14.5 テンプレートメソッド
| メソッド | 意味 |
|---|---|
void setUp() | これをオーバーライドして、実行するテストに関連するオブジェクトの作成を行います。テストケース内で各テストが実行されるたびに、setUp() が毎回コールされます。 |
void tearDown() | これをオーバーライドして、実行するテストに関連する、もう必要なくなったオブジェクトの後始末を行います。テストケース内で各テストが実行されるたびに、setUp() が毎回コールされます。一般に、tearDown() で明示的に後始末する必要があるのは外部リソース (例えばファイルやソケットなど) だけです。 |
PHPUnit2_Framework_TestSuite は複数の
PHPUnit2_Framework_Test を組み合わせたものです。
簡単に言うと、このクラスには複数のテストケースが含まれており、
テストスイートを実行するとそれらの全てのテストが実行されます。
テストスイートは composite なので、テストスイートの中に別のテストスイートを含め、
さらにそのテストスイートの中には別のテストスイートが含まれており……
といったことも可能です。これにより、
いろいろなところから集めたテストをひとまとめにすることが簡単になります。
run(PHPUnit2_Framework_TestResult $result) および
countTestCases() の 2 つに加え、
PHPUnit2_Framework_TestSuite は名前つきインスタンス、
名前なしインスタンスを作成するためのプロトコルも用意しています。
PHPUnit2_Framework_TestSuite
のインスタンスを作成するための方法を
表14.6「名前つき、あるいは名前なしインスタンスの作成」
に示します。
表14.6 名前つき、あるいは名前なしインスタンスの作成
| メソッド | 意味 |
|---|---|
__construct() | 空のテストスイートを返します。 |
__construct(string $theClass) | test* という名前のメソッドを持つ、$theClass という名前のクラスのインスタンスを含むテストスイートを返します。$theClass という名前のクラスが存在しない場合は、$theClass という名前の空のテストスイートが返されます。 |
__construct(string $theClass, string $name) | test* という名前のメソッドを持つ $theClass という名前のクラスのインスタンスを含む、$name という名前のテストスイートを返します。 |
__construct(ReflectionClass $theClass) | test* という名前のメソッドを持つ、$theClass が指すクラスのインスタンスを含むテストスイートを返します。 |
__construct(ReflectionClass $theClass, $name) | test* という名前のメソッドを持つ $theClass が指すクラスのインスタンスを含む、$name という名前のテストスイートを返します。 |
string getName() | テストスイートの名前を返します。 |
void setName(string $name) | テストスイートの名前を設定します。 |
PHPUnit2_Framework_TestSuite には、
PHPUnit2_Framework_Test
を追加したり取得したりするためのプロトコルも用意されています。これを
表14.7「テストの追加、取得のためのプロトコル」
にまとめます。
表14.7 テストの追加、取得のためのプロトコル
| メソッド | 意味 |
|---|---|
void addTest(PHPUnit2_Framework_Test $test) | テストスイートに $test を追加します。 |
void addTestFile(string $filename) | 指定したソースファイルで定義されているクラスをテストスイートに追加します。 |
void addTestFiles(array $filenames) | 指定したソースファイルで定義されているクラスをテストスイートに追加します。 |
int testCount() | このテストスイートに直接登録されているテストの数を返します (再帰的には検索しません)。 |
PHPUnit2_Framework_Test[] tests() | このテストスイートに直接登録されているテストを返します。 |
PHPUnit2_Framework_Test testAt(int $index) | $index 番目のテストを返します。 |
例14.3「テストスイートの作成および実行」 に、テストスイートを作成して実行する方法を示します。
例14.3 テストスイートの作成および実行
<?php
require_once 'PHPUnit2/Framework/TestSuite.php';
require_once 'ArrayTest.php';
// ArrayTest クラスのテストを含む
// テストスイートを作成します。
$suite = new PHPUnit2_Framework_TestSuite('ArrayTest');
// テストを実行します。
$suite->run();
?>
階層化されたテストケースを組み合わせた PHPUnit2_Framework_TestSuite
の使用例として、PHPUnit 自身のテストスイートを見てみましょう。
例14.4「AllTests クラス」 は
Tests/AllTests.php の一部を抜粋したもの、そして
例14.5「Framework_AllTests クラス」 は
Tests/Framework/AllTests.php の一部を抜粋したものです。
例14.4 AllTests クラス
<?php
if (!defined('PHPUnit2_MAIN_METHOD')) {
define('PHPUnit2_MAIN_METHOD', 'AllTests::main');
}
require_once 'PHPUnit2/Framework/TestSuite.php';
require_once 'PHPUnit2/TextUI/TestRunner.php';
require_once 'Framework/AllTests.php';
// ...
class AllTests {
public static function main() {
PHPUnit2_TextUI_TestRunner::run(self::suite());
}
public static function suite() {
$suite = new PHPUnit2_Framework_TestSuite('PHPUnit');
$suite->addTest(Framework_AllTests::suite());
// ...
return $suite;
}
}
if (PHPUnit2_MAIN_METHOD == 'AllTests::main') {
AllTests::main();
}
?>
例14.5 Framework_AllTests クラス
<?php
if (!defined('PHPUnit2_MAIN_METHOD')) {
define('PHPUnit2_MAIN_METHOD', 'Framework_AllTests::main');
}
require_once 'PHPUnit2/Framework/TestSuite.php';
require_once 'PHPUnit2/TextUI/TestRunner.php';
require_once 'Framework/AssertTest.php';
// ...
class Framework_AllTests {
public static function main() {
PHPUnit2_TextUI_TestRunner::run(self::suite());
}
public static function suite() {
$suite = new PHPUnit2_Framework_TestSuite('PHPUnit Framework');
$suite->addTestSuite('Framework_AssertTest');
// ...
return $suite;
}
}
if (PHPUnit2_MAIN_METHOD == 'Framework_AllTests::main') {
Framework_AllTests::main();
}
?>
Framework_AssertTest クラスは、
PHPUnit2_Framework_TestCase
を継承した一般的なテストケースです。
Tests/AllTests.php を実行すると、TextUI
テストランナーを使用し、すべてのテストを実行します。一方
Tests/Framework/AllTests.php を実行すると、
PHPUnit2_Framework_* クラスのテストのみを実行します。
PHPUnit テストスイートの実行結果は、このようになります。
php AllTests.php
PHPUnit 2.3.0 by Sebastian Bergmann.
.........................................
.........................................
.......
Time: 4.642600
OK (89 tests)
これらのテストを実行している間は、実行したテストの数・失敗したテスト・
テストの所要時間などをどこかに保存しておかなければなりません。
これらの結果を収集するのが PHPUnit2_Framework_TestResult
です。ひとつの PHPUnit2_Framework_TestResult が、
テスト全体で使いまわされます。テストの実行結果や失敗の内容は
PHPUnit2_Framework_TestResult に記録されていき、
実行が終了すると、PHPUnit2_Framework_TestResult
には全てのテストの概要が含まれるようになります。
PHPUnit2_Framework_TestResult は、
テストの進行状況を知りたい他のオブジェクトから参照されることもあります。
例えば、グラフィカルなテストランナーは PHPUnit2_Framework_TestResult
を監視し、各テストの開始時にプログレスバーを更新するでしょう。
表14.8「TestResult の外部プロトコル」 は、
PHPUnit2_Framework_TestResult
の外部プロトコルをまとめたものです。
表14.8 TestResult の外部プロトコル
| メソッド | 意味 |
|---|---|
void addError(PHPUnit2_Framework_Test $test, Exception $e) | 実行中の $test から予期せぬ $e がスローされたことを記録します。 |
void addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) | 実行中の $test から予期せぬ $e がスローされたことを記録します。 |
PHPUnit2_Framework_TestFailure[] errors() | 記録されたエラーを返します。 |
PHPUnit2_Framework_TestFailure[] failures() | 記録された失敗を返します。 |
PHPUnit2_Framework_TestFailure[] notImplemented() | 記録された未完了テストを返します。 |
int errorCount() | 記録されたエラーの数を返します。 |
int failureCount() | 記録された失敗の数を返します。 |
int notImplementedCount() | 未完了のテストケースの数を返します。 |
int runCount() | 実行したテストケースの総数を返します。 |
boolean wasSuccessfull() | すべてのテストの実行に成功したかどうかを返します。 |
boolean allCompletlyImplemented() | すべてのテストが完全に実装されているかどうかを返します。 |
void collectCodeCoverageInformation(bool $flag) | コードカバレッジ情報の収集を有効あるいは無効にします。 |
array getCodeCoverageInformation() | 収集したコードカバレッジ情報を返します。 |
PHPUnit2_Framework_TestResult
のオブザーバを登録したい場合は、PHPUnit2_Framework_TestListener
を実装する必要があります。これを登録するには、
表14.9「TestResult および TestListener」
に示した addListener() を使用します。
表14.9 TestResult および TestListener
| メソッド | 意味 |
|---|---|
void addListener(PHPUnit2_Framework_TestListener $listener) | $listener を登録し、テスト結果の内容が更新された場合にその内容を受け取るようにします。 |
void removeListener(PHPUnit2_Framework_TestListener $listener) | 更新を受け取る $listener の登録を解除します。 |
表14.10「TestListener のコールバック」 に、テストリスナーが実装するメソッドを示します。 例15.3「シンプルなテストリスナー」 も参照ください。
表14.10 TestListener のコールバック
| メソッド | 意味 |
|---|---|
void addError(PHPUnit2_Framework_Test $test, Exception $e) | $test が $e をスローしました。 |
void addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) | $test がアサーションに失敗し、PHPUnit2_Framework_AssertionFailedError 系がスローされました。 |
void addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) | $test は完了しませんでした。 |
void startTestSuite(PHPUnit2_Framework_TestSuite $suite) | $suite の実行が始まります。 |
void endTestSuite(PHPUnit2_Framework_TestSuite $suite) | $suite の実行が終了しました。 |
void startTest(PHPUnit2_Framework_Test $test) | $test の実行が始まります。 |
void endTest(PHPUnit2_Framework_Test $test) | $test の実行が終了しました。 |