MozMill を使って Firefox 拡張機能のテストを行う方法
これまで Firefox 拡張機能のテストをどうやって書くのがいいかずっと悩んでいたのですが (悩みつつも QUnit を使ってテストを書いていました)、このあいだ MozMill というのを見つけて、使ってみたらなかなか良かったので紹介します。
MozMill とは
MozMill は Mozilla 製品 (Firefox や Thunderbird などの Gecko ベースのアプリケーション) の自動テストを書くためのテスティングフレームワークです。 MDN のドキュメントには拡張機能としてインストールすることも、コマンドラインツールとしてインストールすることもできると書かれていますが、拡張機能は Mozilla Add-ons から削除されてしまっているようでした。
MozMill は Firefox 自体のテストにも使われているということですが、Firefox 拡張機能のテストに使用することもできます。
- 参考: Mozmill | MDN
MozMill を使って Firefox 拡張のテストを実行する
MozMill のインストールから Firefox 拡張機能のテストを実行するところまでの簡単な流れを説明します。
MozMill のインストール
コマンドラインツールとしての MozMill をインストールします。 Debian や Ubuntu では、下記コマンドでインストールできます。 (システムにインストールされている Python を使用します。) pip コマンドは Python のパッケージ管理システムです。
$ sudo apt-get install python-pip python-dev $ sudo pip install mozmill mercurial
その他の OS の場合は MDN のドキュメントを見てください: コマンドライン版 MozMill のインストール方法
MozMill によるテストの実行
とりあえず Firefox 拡張機能は関係なしに、単に JavaScript のテストを実行させてみます。
MozMill では、「test」 で始まる名前の関数がテストの関数だとみなされるようです。 なので、
function test_XXX() { // ... }
というような感じでファイル中に関数定義を書いていけばよいことになります。 とはいえ、他のテスティングフレームワークに書きかえる場合のことを考えると、テスト定義用の関数を作った方が良いでしょう。 (特に非同期処理のテストに関しては。)
var assertions = {}; Cu.import("resource://mozmill/modules/assertions.js", assertions); // assert による値の検査を行うと、失敗時にはそれ以降の処理が行われない var assert = new assertions.Assert(); // expect による値の検査を行うと、失敗時もそれ以降の処理が行われる var expect = new assertions.Expect(); // --- テスト定義のための関数 --- // XXX 同じ名前のテストが定義されたら上書きされてしまう var global = this; function defineTest(testName, testFunc) { global["test:" + testName] = testFunc; } function defineAsyncTest(testName, testFunc) { global["test:" + testName] = function () { var isDone = false; var callback = function () { return isDone }; testFunc(function () { isDone = true }); assert.waitFor(callback); }; } // --- テストの記述 --- defineTest("同期的なテスト", function () { assert.ok(true, "good"); assert.equal("1", "1", "1 is 1"); assert.pass("good"); }); defineAsyncTest("非同期処理のテスト", function (done) { var timer = {}; Components.utils.import("resource://gre/modules/Timer.jsm", timer); timer.setTimeout(function () { expect.fail("not good"); expect.pass("good"); done(); }, 1000); });
上のようなコードを書いて (test-example.js とする)、次のコマンドを実行するとテストが走ります。
$ mozmill --binary=$HOME/local/firefox-nightly/firefox --test=test-example.js
--binary
オプションは Firefox 本体のパス。 --test
オプションは実行するテストファイル。
MozMill を使ってみての感想
- Firefox との親和性は高い。
- Gecko ベースのアプリケーション用のテスティングフレームワークなので当然ではある。
- mozmill コマンドを叩いたらアドオンをインストールしたうえで Firefox を起動してテスト実行してくれるという便利さ。
- DOM 要素をラッピングしてユーザーの行動 (クリックなど) をシミュレートしてくれる機能もあるっぽい (Mozmill Element Object - Mozmill | MDN; ここら辺はまだ試してない。)
ドキュメントは少ない。→ MDN 上を探したら結構あるけど、リンク切れになってたりするところもあって探すのが結構大変。- ドキュメントはあまりないと思っていい。 ここに書いたようなテストの実行をするのにもソースコードを読んだりして調べる必要があった。
- とはいえここに書いた程度のテストが書ければあとはまあなんとかなりそうな気もする。
Firefox 周りのテストの話 (追記)
本記事公開後に saneyuki さんが Firefox 周りのテストの話についてつぶやかれていました。 Mochitest というのもあるんですね。
今、MozMillってどれくらい使われてたかなー。try chooserだと"Tb only"って書かれてるし。
— サーボ太郎 (@saneyuki_s) 2013, 9月 29
FirefoxそのもののUI testは、Mochitest使ってる。https://t.co/5AbO3Bt7QC コードサンプル多いけど、アドオン用途には基本向かない。
— サーボ太郎 (@saneyuki_s) 2013, 9月 29