Home > Latest topics

Latest topics > MozUnitで単体テスト

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

MozUnitで単体テスト - Jan 22, 2007

MozLabに含まれてる単体テストツールのMozUnitの使いかたが分からない、っていうか真面目にプログラミング勉強したことないから単体テストっていうのがどういう物なのかすらわかってない。説明が全然ないし、普通に他のテスト用のツールを使い慣れた人でないと使えないとかそういう物なのだろうか?

とりあえず試しに動かしてみたけど、何が嬉しいのかいまいち分からない。隠し設定使えば普通にJSコンソールにエラーがリアルタイムで表示されるし、エラー表示だけじゃどこがいけないのか分からないとかいっても結局の所JSデバッガで一行ずつ見ていかないと分からない所だってあるし……自動制御で動かすのも、userChrome.jsとかで自分でスクリプト書いてやるのとの違いが分からない。特に、ブラウザの読み込みが完了したタイミングでのテストとか。

日曜プログラマもどきみたいなのが手を出していい物じゃあないんじゃないのか、これは。

追記。MozUnitのソースコード見てああでもないこうでもないと頭の中で検証してやっと使い方が理解できた。

動画で紹介されてるのは非同期処理の例なんだけど、これで例えばブラウザの読み込みを待ってからテストを実行するとかそういうのをやろうとすると、全然うまくいかない。

こういう場合はコールバック関数とかイベントリスナとかを使って、テストしたい状態になるのを待ってからテストしてやらなきゃいかんのだけど、その方法が全然分からなかった。MozUnitのページには、何やらオプションを指定すると非同期でない(変な日本語だ……)テストができるとか書いてあるんだけど、英語だし略語と技術的専門用語との区別がつかんしで、ちんぷんかんぷんだった。

結論から言うと、async型のテストを作る場合は「setUp」メソッドに渡されるコールバック関数を使うというのが鍵だった。このコールバック関数を実行しないと、処理が一歩も進まない。

以下、実際に試してみたテストケースの例。


var TestCase = mozlab.mozunit.TestCase;
var assert = mozlab.mozunit.assertions;

/* XPConnect特権付きで実行されるので、
   XPCOMコンポーネントも普通に利用できる。 */
var WindowManager = Components
               .classes['@mozilla.org/appshell/window-mediator;1']
               .getService(Components.interfaces.nsIWindowMediator);
var win = WindowManager.getMostRecentWindow('navigator:browser');

// var t;
// var t = null;
var t = {};
/* クロージャ用に変数の宣言だけしておこうとすると、実行時に
   エラーになる。
   (実行時にTestCaseのインスタンスを探すために、このファイルの
     すべてのグローバル変数のプロトタイプチェーンを辿ろうとしてしまうため、
     undefinedな変数があるとエラーになる)
   なので、グローバル変数は面倒でもすべて何らかのオブジェクトにしておく
   必要がある。 */

var count = 0;
var uris = [
    'http://www.google.com/',
    'http://spreadfirefox.jp/foxkeh/',
    'http://piro.sakura.ne.jp/xul/unknown/'
  ];

/* {runStrategy: 'async'} というオプションをコンストラクタの
   第2引数に指定するとコールバック関数を使ったテストが可能になる。 */
var testcase = new TestCase('this is a test!', {runStrategy: 'async'});

testcase.tests = {
  /*  "setUp" はテストが実行される前に毎回呼ばれる。
      ここに渡されたコールバック関数に対して"ok"という文字列を渡すと、
      テストが実行される。
      "ko"という文字列を渡すと、テストを行わずに処理を進める。
      (テストを行わず "tearDown" を実行する。
        テストのカウンタは進まない。) */
  setUp : function(aCallback) {
    t = win.gBrowser.addTab(uris[count++]);
    t.linkedBrowser.addEventListener('load', function(aEvent) {
      t.linkedBrowser.removeEventListener('load', arguments.callee, true);
      aCallback('ok');
    }, true);
  },

  /* "tearDown" はテストが完了する度に毎回呼ばれる。
     テストが成功しても失敗しても、ここに処理が回ってくる。
     テストで行った処理の後始末はここでやる。 */
  tearDown : function() {
    win.gBrowser.removeTab(t);
  },

  // 以下、テストの定義。

  'test1: normal page load' : function() {
    // ページがちゃんと読み込まれていればテストをパスする
    assert.equals(t.linkedBrowser.contentTitle, 'Google');
  },

  'test2: redirected page load' : function() {
    // きちんとリダイレクトされていればテストをパスする
    assert.equals(t.linkedBrowser.currentURI.spec, 'http://foxkeh.jp/');
  },

  'test3: ' : function() {
    // こんなリダイレクトは無いのでテストをパスしない
    assert.equals(t.linkedBrowser.currentURI.spec,
                         'http://piro.sakura.ne.jp/xul/_unknown.html');
  }
}

たったこれだけのことを理解するのに半日費してしまったよ……無能な自分が嫌になる。

分類:Mozilla > 拡張機能, , , , , , 時刻:23:20 | Comments/Trackbacks (0) | Edit

Comments/Trackbacks

TrackBack ping me at


の末尾に2014年1月19日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2007-01-22_mozlab.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2014年1月19日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード