UnitTestForPlugins
| Table of Contents |
Last Modified. May 19 2006.
UnitTest for Pukiwiki Plugins - 古い
#Pukiwiki Plus! でテストしているので、この alltest.ini.php は通常の Pukiwiki ではうまくないかもしれないことに後で気づいた。
#新しい alltest.ini.php を用意しなければいけなくなった模様 02/01/2007。非常に面倒くさい。unset さえなければいいわけで。
UnitTest とは
省略。
とりあえず試してみよう
Pukiwikiでやりやすいように、ある程度枠組みを作ってしまいました。
- index.php (pukiwiki.php)
- pukiwiki.ini.php
- plugin/
alltest.php
alltest.ini.php- test/
- PHPUnit.php
- PHPUnit/
リンクからダウンロードして、上の構成となるように配置してください。
PHPUnit は本家 http://pear.php.net/package/PHPUnit2/download
からダウンロードしてください。
ブラウザから http://YourPukiwikiURL/alltest.php
のようにアクセスし、hoge をチェックし、テストを走らせてみましょう。動けばとりあえずOKです。動かなければ・・・わかりません。
御分かりの通り、追加する場合は、plugin ディレクトリにプラグインを、 test ディレクトリにテストコードをおいていってください。
テストコードの作り方
まず、プラグインフォルダにプラグインをおきます。 以下のような hoge.inc.php だとします。
<?php
function plugin_hoge_convert()
{
$args = func_get_args();
return array_pop($args); // last argument
}
function plugin_hoge_inline()
{
$args = func_get_args();
return array_pop($args); // {} is being sanitized (htmlspecialchars).
}
?>
次に test ディレクトリにテストコードをおきます。 以下のような hoge.php かもしれません。
<?php
require_once 'PHPUnit.php';
class test_hoge extends PHPUnit_TestCase {
function test_hoge($name)
{
$this->PHPUnit_TestCase($name);
}
function setUp()
{
}
function tearDown()
{
}
function test_exist()
{
$this->assertTrue( exist_plugin('hoge') );
}
function test_exist_convert()
{
$this->assertTrue( exist_plugin_convert('hoge') );
}
function test_exist_inline()
{
$this->assertTrue( exist_plugin_inline('hoge') );
}
function test_convert()
{
$lines = array();
$lines[] = '#hoge(a,b,<i>)';
$this->assertEquals( "<i>\n", convert_html( $lines ) );
$lines = array();
$lines[] = '#hoge(a,b){{';
$lines[] = '<i>';
$lines[] = '}}';
$this->assertEquals( "<i>\r\n", convert_html( $lines ) );
$this->assertRegExp( "/<i>/", convert_html( $lines ) );
}
function test_inline()
{
$string = '&hoge(a,b){<i>};';
$this->assertEquals( "<i>", make_link( $string ) );
}
}
?>
クラス名は test_hoge (ディレクトリ名_ファイル名) にしなければいけません*1。
UnitCase 経験者の方はなんとなくわかると思います。真似で書いてみてください。
PHPUnit の説明は端折るので、
本家のドキュメント PHPUnit Pocket Guide
を参照してください。
一応少しばかりソースコードの説明をしておきますと、Pukiwiki の関数、 lib/plugin#exist_plugin はプラグインの存在確認とともにプラグインの require を行います。 なので require は書いていません。convert_html は Pukiwiki のWiki文法をHTMLに変換するエンジンです。make_link は [[]] なリンクやインラインプラグインを変換します。convert_html は内部でこれを使用しています。
convert のほうで \n だったり \r\n だったりしていますが、よくわかっていません。 プラグインもテストコードも改行コードは \n (LF) にしているのですが。 テスト環境は Pukiwiki Plus i18n (UTF-8) on apache on Windows なのですが、\r\n を出力したりすることもあるのでしょうか? 適当に改行コードは合わせてみてください。
- 一言:Pukiwiki プラグインは最終的に HTML コードを出力したいわけですが、HTML コードのテストはし辛いですよね。
- 二言:UnitTest のコツは先にテストを書いてそれにより仕様を決め、その後本体のコーディングをすることです。本当は。
- 三言:プラグイン内で定義した関数を呼ぶ場合は call_user_func
や call_user_func_array
が役に立つかもしれません。
UnitTest 実行スクリプト
UnitTest を実行する alltest.php の内容は以下のようになっています。
<?php
require 'alltest.ini.php';
define('TEST_DIR', 'test/');
require_once 'PHPUnit/GUI/HTML.php';
require_once 'PHPUnit/GUI/SetupDecorator.php';
$gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_HTML());
$gui->getSuitesFromDir(TEST_DIR, '.*.php$');
$gui->show();
?>
このプログラムは UnitTest の HTML GUI を提供します。 alltest.ini.php で Pukiwiki の定数、関数を読み込むように初期化しています。
alltest.php と同じ階層に 'test/' ディレクトリを作成し、その中にテストファイルを置くと、 自動で読み込んでくれます。 この際、ファイル名が xxx.php なら、クラス名を test_xxx と作成しなければいけないようです。 PHPUnit_GUI_SetupDecorator の仕様、もとい PEAR 準拠らしいです。
Pukiwiki 定数、関数の読み込み
Pukiwiki 定数、関数の読み込みをする alltest.ini.php を作成しました。
非常にやりにくかったです。
Pukiwiki は index.php 内、またそこから読み込んでいる lib/pukiwiki.php 内でも定数を設定していますが、 そのまま、require 'index.php'; としては pukiwiki 自体が実行されてしまうので、実行部分は端折った定数宣言部分だけをコピーする必要があります。
そうして、lib/pukiwiki.php を辿っていくと、その内部で lib/init.php を require しています。 これが曲者で、いくつかの環境変数を unset しているので、PHPUnit_GUI_HTML が正常動作しなくなります。 なので lib/init.php をコピーし、unset を片っ端からコメントアウトしています。
とりあえず動いているように見えます。
#Pukiwiki Plus のコードを改変したので、Plus 用になっています。本家用は自分が使わないので誰か・・・
PukiWiki API のオーバーライド
例えば ../lsx.inc.php のように PukiWiki API関数、 lib/file.php#get_existpages を使用している場合、実際にページを作らずにテストしたいわけです。 その場合、自分は以下のようにしています。
- ../xxx.inc.php のようにクラス化。クラス PluginXxx を作成し、その中でコードを書く。
- PukiWiki API を直接呼ばずに、そのクラス内にAPI関数と同名の関数を用意し、そこから呼ぶようにラッピング。
function get_existpages() { return get_existpages(); }少し面倒くさくなるが、プラグイン内では $this->get_existpages(); のように呼ぶようにする。 - テスト用ファイルで、require PLUGIN_DIR . 'xxx.inc.php'; をし、テスト用のクラス PluginXxxUnitTest extends PluginXxx を作成
- PluginXxxUnitTest 内で function get_existpages() をオーバーライド。ここで適当にページ配列を返す。
- テスト用ファイルで define('PLUGIN_UNITTEST', true) を宣言し、プラグイン内でそれにより PluginXxxUnitTest を使用するか PluginXxx を使用するか分岐する。
../xxx.inc.php では何もオーバーライドする必要がありませんが、テンプレートとして枠組みだけ作ってあるので参考にしてみてください。../contentsx.inc.php, ../lsx.inc.php では実際に使用しているのでそれらも参考にしてみてください。
#もっとうまい方法があったら教えてください。
参考
- http://www.phpunit.de/wiki/Main_Page
PHPUnit本家 - dev:UnitTest
- dev:BugTrack2/113
テスト関連 - dev:BugTrack2/162
プラグインのUnitTest
- dev:BugTrack2/113
- PHPUnitをPukiWikiのプラグインでも使ってみよう!-okkezのPukiWiki



