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で指定したディレクトリの全てのファイルを読み込み、パターンにマッチしたファイルを取得するという流れになっています。
このため、
- ユニットテストのソースは特定のディレクトリに作成しておいて、そのディレクトリ名を指定する。
- ユニットテストのソースは"...Test.php"のように特定の形式で作成する
テスト抽出部のソースは次のようになります。
- 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 実行例
次のようにしてテストを実行します。
- テストランナー"alltests.php"にアクセスします。
![[初期画面]](images/phpunit_gui-01.jpg)
- テストをしたい項目にチェックを押して[run tests]ボタンをクリックします。
![[実行画面]](images/phpunit_gui-02.jpg)
上記のようにグリーンのバーだけならエラーはありません。
後は、適宜テストを実行しながらシステムを開発します。