第14章 PHPUnit API

たいていの場合は、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_AssertPHPUnit2_Framework_TestPHPUnit2_Framework_TestCasePHPUnit2_Framework_TestSuite および PHPUnit2_Framework_TestResult の関係を 図14.1「PHPUnit の 5 つの基本クラス/インターフェイス」 に示します。

図14.1 PHPUnit の 5 つの基本クラス/インターフェイス

PHPUnit の 5 つの基本クラス/インターフェイス


PHPUnit2_Framework_Assert

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)$conditionFALSE の場合にエラーを報告します。
void assertTrue(bool $condition, string $message)$conditionFALSE の場合にエラー $message を報告します。
void assertFalse(bool $condition)$conditionTRUE の場合にエラーを報告します。
void assertFalse(bool $condition, string $message)$conditionTRUE の場合にエラー $message を報告します。
void assertNull(mixed $variable)$variableNULL でないときにエラーを報告します。
void assertNull(mixed $variable, string $message)$variableNULL でないときにエラー $message を報告します。
void assertNotNull(mixed $variable)$variableNULL の場合にエラーを報告します。
void assertNotNull(mixed $variable, string $message)$variableNULL の場合にエラー $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 のボトルネックメソッドをまとめます。

表14.2 ボトルネックメソッド

メソッド意味
void fail()エラーを報告します。
void fail(string $message)エラー $message を報告します。


PHPUnit2_Framework_Test

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

テストケースクラスは PHPUnit2_Framework_TestCase クラスを継承して作成します。たいていの場合は、 テストスイートから自動的にテストを実行させることになるでしょう。 この場合、(規約により) 各テストは test* という名前のメソッドにしておかなければなりません。

PHPUnit2_Framework_TestCasePHPUnit2_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_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 は、 テストの進行状況を知りたい他のオブジェクトから参照されることもあります。 例えば、グラフィカルなテストランナーは 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 の実行が終了しました。


パッケージの構成

この本で取り上げたクラスの多くは PHPUnit2/Framework にあるものです。ここには PHPUnit のすべてのパッケージが含まれています。

  • PHPUnit2/Framework

    PHPUnit の基本クラス。

  • PHPUnit2/Extensions

    PHPUnit フレームワークの拡張。

  • PHPUnit2/Runner

    テストの実行を抽象化したクラス。

  • PHPUnit2/TextUI

    テキストベースのテストランナー。

  • PHPUnit2/Util

    他のパッケージから使用するユーティリティクラス群。