PHPUnit_GUI_SetupDecoratorを使って指定ディレクトリのテストをまとめて実行する方法

PHP Evo / PEAR hacks

PHPUnitの使い方(3): PHPUnit_GUI_SetupDecoratorを使う

Ver 1.0 '04/04/09
Ver 1.1 '04/07/20 PEAR hacksに移動、書き直し
PHP Evo / PEAR hacks / PHPUnitの使い方(3): PHPUnit_GUI_SetupDecoratorを使う

PHPUnitのWeb用GUIツールであるPHPUnit_GUI_SetupDecoratorを使って指定ディレクトリ上のテストを実行する方法


1. PHPUnit_GUI_SetupDecoratorとは

1.1 PHPUnit_GUI_SetupDecoratorとは何か?

PHPUnitではWeb上でテスト結果をわかりやすくビジュアルに表示するモジュールGUIがあります。
PHPUnit_GUI_SetupDecoratorは指定ディレクトリ上のテストをまとめて追加するためのモジュールです。

1.2 PHPUnit_GUI_SetupDecoratorの使い方

PHPUnit_GUI_SetupDecoratorは次のように使います。

    8|require_once 'PHPUnit/GUI/HTML.php';
    9|require_once 'PHPUnit/GUI/SetupDecorator.php';
   10|
   11|// run Test Suites
   12|$gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_HTML());
   13|$gui->getSuitesFromDir('Tests','.*Test.php$');
   14|$gui->show();
この場合、Testsディレクトリの下にある'...Test.php'というファイルにあるテストを実行します。
ここで肝になるのは、
   13|$gui->getSuitesFromDir('Tests','.*Test.php$');
の部分です。
第1引数の"Tests"はUnitTestを検索するディレクトリを指定しています。
第2引数の".*Test.php$"は、UnitTestファイルを抽出するための検索パターンです。この場合は、Test.phpで終わるファイルをUnitTestファイルとして抽出しています。

2. PHPUnit_GUI_SetupDecoratorを解析する

2.1 PHPUnit_GUI_SetupDecoratorのUnitTest抽出方法

SetupDecorator.phpのソースを解析してテストクラスの取得方法を解説します。
PHPUnit 1.0.1のソースを解析しています。

まずは、ファイル名読み込み部のソースを解析します。

PHPUnit/GUI/SetupDecorator.php
 105:    function _getFiles($dir,$filenamePattern,$exclude,$rootDir)
 106:    {
 107:        $files = array();
 108:        if ($dp=opendir($dir)) {
 109:            while (false!==($file=readdir($dp))) {
 110:                $filename = $dir.DIRECTORY_SEPARATOR.$file;
 111:                $match = true;
 112:                if ($filenamePattern && !preg_match("~$filenamePattern~",$file)) {
 113:                    $match = false;
 114:                }
 115|                if (sizeof($exclude)) {
 116|                    foreach ($exclude as $aExclude) {
 117|                        if (strpos($file,$aExclude)!==false) {
 118|                            $match = false;
 119|                            break;
 120|                        }
 121|                    }
 122|                }

この_getFilesはgetSuitesFromDirから呼び出される内部メソッドです。
最初の3つの引数はgetSuitesFromDirで指定する3つの引数です。 つまりテストを読み込むディレクトリ、テストファイル名のファイル名パターン、テストとして認識しないファイルのリストの3つです。

このソースを解説すると、$dirで指定したディレクトリの全てのファイルを読み込み、パターンにマッチしたファイルを取得するという流れになっています。
このため、

必要があります。

テスト抽出部のソースは次のようになります。

PHPUnit/GUI/SetupDecorator.php
 123:                if (is_file($filename) && $match) {
 124:                    $className = str_replace(DIRECTORY_SEPARATOR, '_', substr(str_replace($rootDir, '', $filename), 1));
 125:                    $className = basename($className,'.php');   // remove php-extension
 126:                    $files[$className] = $filename;
 127:                }

124行目では、取得したファイル名から$rootDirを消去しています。
この$rootDirは105行目のソースにあるように、_getFilesメソッドの引数です。
呼び出し元は以下のようになります。

81| $files = $this->_getFiles($dir,$filenamePattern,$exclude,realpath($dir.'/..'));
この$dirはTestを作成したときに指定したディレクトリです。
$rootDirはテストが存在するディレクトリの親ディレクトリの絶対パス。つまり、テストを実行するphpファイルが存在するディレクトリです。
124行目ではファイル名からこのディレクトリ部を消去しています。つまり、テストが存在するWeb上のフルパスを取得しています。

次にsubstrで最初の1文字を削除しています。
取得したフルパスは'/'(あるいは'\')ではじまっているので、それを削除しています。

最後にstr_replaceで'/'(あるいは'\')を'_'に変換しています。
これによりディレクトリおよびファイル名を一つの名前として取得しています。

125行目では、取得したクラス名から拡張子を削除しています。
以上でクラス名の作成は終了です。

まとめると、テストケースのファイル名がTests/GUITest.phpと場合、クラス名は'Tests_GUITest'となります。

126行目では作成したクラス名とファイル名のペアをリストに追加しています。
こうして、実行するテストケースのリストを作成します。

2.2 UnitTestの抽出方法を変更する

2.1でテストクラスはパス名付きで作成されていました。
ここではファイル名だけからクラスを作成するようにパッチを当てます。
ソースは次のようになります。

PHPUnit/GUI/SetupDecorator.php
 123:                if (is_file($filename) && $match) {
 124:                    $className = str_replace(DIRECTORY_SEPARATOR, '_', substr(str_replace($rootDir, '', $filename), 1));
 125:                    $className = $filename;
 126:                    $className = basename($className,'.php');   // remove php-extension
 127:                    $files[$className] = $filename;
 128:                }

これでユニットテストソースのファイル名からテストクラス名を取得するようになります。
この場合、Tests/GUITest.phpというファイルの場合はclass名は'GUITest'となります。

3. PHPUnit_GUI_SetupDecoratorを使う

3.1 テストランナー

ユニットテストを実行するには、テストランナーと呼ばれるソースを作成する必要があります。
テストランナーのソースは以下のようになります。

alltests.php
   1:<?php
   2:// $Id: phpunit-gui.html 2 2007-02-28 14:35:40Z atsushifx $
   3:require_once 'common.inc';
   4:$basedir = aglib::basedir();
   5:$libdir = ".:$basedir:$basedir/aglib:$basedir/PEAR:$basedir/dbObject:/usr/local/lib/php";
   6:ini_set('include_path', $libdir);
   7:
   8:require_once 'PHPUnit/GUI/HTML.php';
   9:require_once 'PHPUnit/GUI/SetupDecorator.php';
  10:
  11:// run Test Suites
  12:$gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_HTML());
  13:$gui->getSuitesFromDir('Tests/','.*Test.php$');
  14:?>
  15:<html>
  16:<head>
  17:    <meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
  18:    <title>UnitTest for aglib</title>
  19:
  20:<body>
  21:<?php
  22:$gui->show();
  23:?>

aglibでは、aglibディレクトリ下にinclude_pathが通っている必要があります。
そのため、4〜6行目でinclude_pathを再設定しています。
それ以降はテストランナー共通の記述です。
$guiにPHPUnit_GUI_SetupDecoratorのインスタンスを作成し、getSuitesFromDirメソッドで指定ディレクトリ下のユニットテストを登録しています。
その後、showメソッドでテストの一覧とテスト結果を表示します。

なお、ユニットテストはTestsディレクトリ下に...Test.phpというファイル名で作成します。

3.3 実行例

次のようにしてテストを実行します。

  1. テストランナー"alltests.php"にアクセスします。
    [初期画面]
  2. テストをしたい項目にチェックを押して[run tests]ボタンをクリックします。
    [実行画面]

上記のようにグリーンのバーだけならエラーはありません。
後は、適宜テストを実行しながらシステムを開発します。


$Revision: 2 $
$Date: 2007-02-28 23:35:40 +0900 (豌エ, 28 2譛 2007) $