今月発売のSoftware Design 4月号にMozunitの記事を書いたのですが、一部ページの都合でカットされた部分がありました。 今回はそのネタを公開しようと思います。
Mozunitとは何でしょう?
Mozunit とは Javascript 向けの単体テストツールです。 Mozlab 拡張の一機能として提供されています。 詳しくは、Mozunit の解説ページを読むか、Software Design 4月号を買ってください(ぉ
Webページに適用してみた例
さて、ここからが本題です。 MozUnit 拡張機能として動作しますので、 XPConnect 特権上で動作します。 そのため、ブラウザ上でできる事は基本的に何でも行なう事が可能です。 つまり、ブラウザの動きをエミュレートするようにテストが書けば Web ページの単体テストにも使えるという事です。 というわけで、実際に見ていきましょう。
サンプルページ
今回利用するのは、Software Design 4月号にも記載している calc.html と calc.js というファイルです。 calc.js は簡単なRPNの実装で、 calc.html がそれを使ったページとなります。 実際に動かしてみるとよいでしょう。
テスト用Javascriptファイル
次に MozUnit が利用する Javascript ファイルが必要です。 test_html.js がそのファイルとなります。 ファイルをダウンロードして、MozUnit 上でテストを実行してみてください。 たぶん、最初の一回目は失敗して、二度目は成功して緑のバーが出てくると思われます。
ソースコードの解説
先ほど書いたように、ブラウザの画面をエミュレートさせている所がポイントです。 実際のコードを見つつ、説明していきましょう。
1 var TestCase = mozlab.mozunit.TestCase;
2 var assert = mozlab.mozunit.assertions;
3
4 var tc = new TestCase('Rpn Calc HTML Test');
5
6 var windowManager = Components.
7 classes['@mozilla.org/appshell/window-mediator;1'].
8 getService(Components.interfaces.nsIWindowMediator);
9 var twin = windowManager.getMostRecentWindow('navigator:browser');
10 var doc = twin.getBrowser().contentDocument;
11
12 tc.tests = {
13 'Rpn Calc HTML Test: 1 2 + ': function() {
14 // HTML Path
15 twin.getBrowser().loadURI("http://note.smellman.homelinux.org/example/mozunit/calc.html");
16 doc.getElementById("a_val").value = 1;
17 doc.getElementById("b_val").value = 2;
18 doc.getElementById("plus_bt").click();
19 assert.equals(doc.getElementById("result").lastChild.nodeValue, 3);
20 }
21 }
最初の4行目まではMozunitのお約束と考えてください。 6行目から10行目までは nsIWindowMediator でブラウザ自体のインスタンスと現在のドキュメントを取得します。 この方法はわりと有名かと思います。
12行目からが実際のテストケースの記述となります。 13行目には関数名らしき場所に文字列が入っています。 これは JUnit などの testXXX メソッドに相当するもので、 MozUnit では関数名が文字列であればテストとみなすようです。 そのため、ドキュメント化が簡略されます。なぜなら、テスト内容がそのままテストケースになるからです。
15行目はブラウザのインスタンスからブラウザを取得して、loadURI メソッドを呼び出します。 この段階で現在のブラウザに指定したURI が開かれます。 16行目、17行目は実際にブラウザからのテキスト入力を再現して、18行目でボタンをクリックするイベントを実行しています。 そして最後の18行目で、実行結果を表示する箇所と期待する結果をassert.equals で比較しています。 以上でプログラムの解説は終了です。簡単ですよね?
ちなみに、最初の一回目に失敗する原因は、loadURIの直後にすぐにgetElementById が呼び出しているので、ロードする前に失敗するようです。 実は雑誌掲載時は全てローカルで実行するように記述していたので、成功していただけで、すげー実行速度に依存しているという罠。 そういう意味では、loadURIの直後にスリープをかけるとかすればなんとかなりそうだなと、いまさら何を言っているんだ俺は。
まとめ
今回は簡単なWebページに対してのテストですが、応用としては不正な文字列を故意に挿入するケースや、hiddenなデータに対する入力テストなどいろいろなパターンがあるかと思います。 特にポイントは、Javascriptを使ったページへのテストでしょう。 単純なCGIであれば普通にテストツールは存在しますが、Javascriptがあるページには使えなく利用を断念した事がありました。Mozunit はその制限を越える事が可能です。 他にもこれ以外のテスト方法があるかと思います。 いろんなテストのアイデアを出し合うと面白いのではないかと思います。