モンモンブログ

技術的な話など

jasmine のテストをページロード時ではなくボタンクリックで実行するには

jasmine テストに時間かかりすぎ!キー!

あるプロジェクトで、600行の JavaScript コードのテストを jasmine で書いたら、テストコードだけで700行を超えてしまいました(笑)

で、テストにかかる時間も、およそ30〜40秒。長い! コードでもテストでもDOM要素をいじりまくってるせいなんですが。(select を選択したり checkbox をチェックしたり)

リロードの度に毎回ここまで時間がかかるようになると、キーッってなります。

(゚皿゚)キー!

自動実行しなきゃいいじゃん

なので jasmine テストをページロード時に自動で実行させる代わりに、ボタンをクリックして手動実行する方法を考えました。

jasmine-1.3.1 の場合

jasmine 1系では、jasmine の初期化・自動実行する部分をライブラリ同梱の SpecRunner.html からコピって使ってると思います。ここを修正すればよし。

ページロード時の自動実行部分をコメントアウトして、代わりに jasmine.execute ってメソッドを追加して、こいつでテストを手動実行出来るようにします。 (jasmine.execute って名前はなんでもよいです。 jasmine.hogehoge でも、なんなら window.hogehoge ってグローバルに置いちゃうのも可。)

    (function() {
        var jasmineEnv = jasmine.getEnv();
        jasmineEnv.updateInterval = 1000;

        var htmlReporter = new jasmine.HtmlReporter();

        jasmineEnv.addReporter(htmlReporter);

        jasmineEnv.specFilter = function(spec) {
            return htmlReporter.specFilter(spec);
        };

        var currentWindowOnload = window.onload;

        // 1. ページロード時の自動実行をコメントアウト
        // window.onload = function() {
        //     if (currentWindowOnload) {
        //         currentWindowOnload();
        //     }
        //     execJasmine();
        // };
        // 
        // function execJasmine() {
        //     jasmineEnv.execute();
        // }

        // 2. jasmine.execute ってメソッドを追加
        jasmine.execute = function () {
            jasmineEnv.execute();
        }
    })();

そしたら、HTML中に手動実行するためのボタンを配置して、

<button id="run-jasmine-test">jasmineテスト実行</button>

このボタンのクリック時にテストを実行するようにしてやればOK。

$('#run-jasmine-test').on('click', function () {
    if (confirm('jasmineテストを実行します。よろしいですか?')) {
        var $button = $(this);
        // ボタンをdisable
        $button.attr('disabled', 'disabled').text('実行中...');
        // 「実行中...」が表示されるように一瞬起動を遅らせる
        setTimeout(function () {
            // さっき定義した jasmine.execute をコール
            jasmine.execute();
            // テスト終了!
            $button.removeAttr('disabled').replaceWith('テスト完了');
        }, 100);
    }
});

jasmine-2.0.0 の場合

jasmine 2系からは、jasmine の初期化・自動実行は lib/jasmine-2.0.0/boot.js が担当するようになりました。

この boot.js の先頭のコメントに「このファイルは好きなようにいじってね (this file can be customized directly)」とあるので、じゃーカスタマイズしちゃいましょ。

このファイルの下の方に window.onload で jasmine を起動する部分があるので、コメントアウトして、さっきと同じように jasmine.execute ってメソッドでテストをキック出来るようにします。

  // ...

  // 1. ページロード時の自動実行をコメントアウト
  // /**
  //  * ## Execution
  //  *
  //  * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
  //  */
  // var currentWindowOnload = window.onload;
  // 
  // window.onload = function() {
  //   if (currentWindowOnload) {
  //     currentWindowOnload();
  //   }
  //   htmlReporter.initialize();
  //   env.execute();
  // };

  // 2. jasmine.execute ってメソッドを追加
  jasmine.execute = function () {
    htmlReporter.initialize();
    env.execute();
  };

  // ...

あとは 1.3.1 の場合と同様、HTML中にボタンを配置して、ボタンクリック時にテストを実行するようにしてやればOKです。

これで

jasmine テストがとんでもなく遅くなっても心穏やかに開発出来るようになりました^^