モンモンブログ

技術的な話など

Rails + Grape 構成で Grape API ファイルを自動再読み込みさせるには

RESTful な API が楽ちんに書ける graperails との組み合わせで使う場合も README に従うだけで簡単に出来ますが、なぜか自動再読み込み (auto reloading) されないって問題にぶち当たります。

development 環境だと model や controller への修正はブラウザをリロードするだけで即反映されますよね。でも grape の api ファイルはなぜか再読み込みされない。いちいち rails サーバを再起動しないといけなくて、非常に困っちゃんです。

(よく理解してませんが rails 上で別の rack フレームワーク(この場合 grape)を動かそうとするとrails の自動再読み込みの仕組みがうまく動かないみたいです)

で、解決方法ですが、grape api ファイルの更新を検知して、無理やり再読み込みさせてやります。

環境

古くてごめんなさい

MacOSX Mavericks
ruby 1.9.3p547 (2014-05-14 revision 45962) [x86_64-darwin13.3.0]
rails-3.2.11
grape-0.9.0

セットアップ

今回は既存の rails アプリに grape を追加しました。手順をざくっと書いておきます。

Gemfile に追記して、

gem 'grape'

インストール

bundle install

grape api ファイルを置くディレクトリを作って

mkdir app/api

Hello World なやつを書いた。(app/api/skimatalk_api.rb)

require 'grape' # この行は grape 単体で動かす場合に必要。rails との組み合わせでは不要
class SkimatalkApi < Grape::API
  format :json

  resource :ehehe do
    desc 'this is a test'
    get :hoe do
      {a: 1, b: 2}
    end
  end
end

rails と組み合わせて実験する前に grape 単体で動かしてみたかったので、同じディレクトリにテスト用の config.ru を作成 (app/api/config.ru)

# coding: utf-8
require './skimatalk_api.rb'
run SkimatalkApi

起動

$ cd app/api
$ rackup
Thin web server (v1.6.2 codename Doc Brown)
Maximum connections set to 1024
Listening on 0.0.0.0:9292, CTRL+C to stop
127.0.0.1 - - [22/Nov/2014 19:54:05] "GET /ehehe/hoe HTTP/1.1" 200 13 0.0971

http://localhost:9292/ehehe/hoe にアクセスすると JSON が表示された。わーい。

f:id:ymdsmn:20141122201157p:plain

(さっき作った config.ru はもう不要なので削除してよいです)

今度はこれを rails 上で動かします。 config/routes.rb に以下を追加して /api/* へのリクエストを grape へ渡すようにします

  mount SkimatalkApi => '/api'

サーバ再起動してから、

rails s

http://localhost:3000/api/ehehe/hoe にアクセス。JSON が表示された。やったね。

f:id:ymdsmn:20141122201201p:plain

でも(さっきも言ったとおり)app/api/skimatalk_api.rb を修正してリロードしても変更が反映されません。困ったね。

解決方法

ここからが本題。 config/initializers/reload_api.rb を作って以下のように書きます

if Rails.env.development?
  api_reloader = ActiveSupport::FileUpdateChecker.new(Dir['app/api/*']) do # app/api/* は環境にあわせて変更すること
    Rails.application.reload_routes! # or do something better here
  end

  ActionDispatch::Callbacks.to_prepare do
    api_reloader.execute_if_updated
  end
end

これだけで、 app/api/* への修正を検知して自動再読み込みしてくれるようになりました。

仕組みは読めばなんとなく分かるよね。分かんなくてもいいよね。

参考

正直このエントリは stackoverflow のこれ↓を解説しただけです。ググって見つけるのに苦労したので書きました…
Ruby on Rails 3 - Reload lib directory for each request - Stack Overflow

jQuery プラグインを bower のレジストリに登録してみた

表題の通り、jQuery プラグイン jquery.narrowsbowerレジストリに登録してみた時の記録です。

bower とは?

こちらが非常に分かりやすかったです。

基礎編の冒頭から(勝手に)引用させて頂きますと、bower とは

Twitter社が作ったフロントエンド用のパッケージマネージャです。 Java で言う MavenRuby で言う gem、 Perl で言う cpan のようなものです。 Node.jsには npm と呼ばれるパッケージマネージャがありますが、それに強く影響を受けています。

ということです。

bower のパッケージは bower レジストリってところで管理されています。 登録済みパッケージの一覧は Bower components ってページで見られます。検索もできます。

この bower レジストリにおいらの jQuery プラグインをいっちょ登録したるぜ!と思い立ちました。

bower レジストリに登録すると何が嬉しいの?

ここに登録しておけば、

bower search で検索したり("sinon" は javascript のテスト用ライブラリです)

$ bower search sinon
Search results:

    sinon git://github.com/cjohansen/Sinon.JS.git
    sinon-chai git://github.com/domenic/sinon-chai.git
    sinonjs git://github.com/blittle/sinon.js.git
(以下略)

bower info でインストール可能なバージョンを調べたり

$ bower info sinon
bower sinon#*               not-cached git://github.com/cjohansen/Sinon.JS.git#*
bower sinon#*                  resolve git://github.com/cjohansen/Sinon.JS.git#*
bower sinon#*                 download https://github.com/cjohansen/Sinon.JS/archive/v1.7.3.tar.gz
bower sinon#*                  extract archive.tar.gz
bower sinon#*                 resolved git://github.com/cjohansen/Sinon.JS.git#1.7.3

{
  name: 'sinon',
  homepage: 'https://github.com/cjohansen/Sinon.JS',
  version: '1.7.3'
}

Available versions:
  - 1.7.3
  - 1.7.1
  - 1.7.0
(中略)
  - 0.6.0
  - 0.5.0
  - 0.2.3

You can request info for a specific version with 'bower info sinon#<version>'

bower install で指定したバージョンをダウンロードしたり出来ます。

$ bower install sinon#1.7.3
bower sinon#1.7.3               cached git://github.com/cjohansen/Sinon.JS.git#1.7.3
bower sinon#1.7.3             validate 1.7.3 against git://github.com/cjohansen/Sinon.JS.git#1.7.3
bower sinon#1.7.3              install sinon#1.7.3

sinon#1.7.3 bower_components/sinon

デフォルトで bower_components ディレクトリ以下にダウンロードされます。

$ ls bower_components/sinon
AUTHORS        LICENSE        build*         lib/           release.sh*
Changelog.txt  README.md      jsl.conf       package.json   test/

JavaScript ライブラリがコマンドラインだけでダウンロード出来ちゃうのがステキです。 いちいちググって、ダウンロードやら git clone やらして、って手間が不要です。

(あと npm の package.jsondependency や devDependency と同様の機能も備えますがここでは触れません)

bower レジストリ登録への道のり

  1. bower.json を作ってリポジトリにコミットして、
  2. リリースバージョン番号をタグ付けして、
  3. bower register コマンドを叩く

という感じ。簡単。順に説明します。

0. bower をインストール

npm でインストール。

$ npm install -g bower
$ bower -v
1.2.8

1. bower.json を作成

bower init コマンドを叩いて質問に答えていくと bower.json の雛形が生成できます。

$ bower init
[?] name: jquery.narrows
[?] version: 0.3.1
[?] description: jQuery Hierselect Plugin
[?] main file: jquery.narrows.js
[?] keywords: jQuery,select,hierselect
[?] authors: simon <xxxxx@gmail.com>
[?] license: MIT
[?] homepage: https://github.com/monmonmon/jquery.narrows
[?] set currently installed components as dependencies? Yes
[?] add commonly ignored files to ignore list? Yes
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry?
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry?
No

{
  name: 'jquery.narrows',
  main: 'jquery.narrows.js',
  version: '0.3.1',
  homepage: 'https://github.com/monmonmon/jquery.narrows',
  authors: [
    'simon <xxxxx@gmail.com>'
  ],
  description: 'jQuery Hierselect Plugin',
  keywords: [
    'jQuery',
    'select',
    'hierselect'
  ],
  license: 'MIT',
  ignore: [
    '**/.*',
    'node_modules',
    'bower_components',
    'test',
    'tests'
  ]
}

[?] Looks good? Yes

それを手直しして、コミット。

$ vim bower.json
$ git add bower.json
$ git commit
$ git push

ちなみに手直しした結果はこんな感じ。

{
  "name": "jquery.narrows.js",
  "version": "0.3.1", // <-gitでのバージョン番号を記述
  "description": "jQuery Hierselect Plugin",
  "license": "MIT",
  "main": "jquery.narrows.js", // <-パッケージのメインとなるファイル
  "ignore": [ // <-bower install した時にダウンロードさせたくないファイルのリスト
    "**/.*",
    "**/*.html",
    "Gruntfile.coffee",
    "node_modules",
    "README.md",
    "package.json",
    "lib",
    "spec"
  ]
}

さっきのBower入門(応用編)にも書かれていますが、 "main" と "ignore" をキチンと書かないと bower install した時に余計なものまでダウンロードしちゃって鬱陶しいので、気をつけて記述します。 (例えば Gruntfile.coffee はライブラリ利用者には不要なので "ignore" に含めてます。)

あと "version" にも要注意。ここに書いたバージョン番号を、次で git tag でタグ付けします。

2. リリースバージョン番号をタグ付け

bower.json に書いたバージョン番号をタグ付けしてやります。 bower はこのバージョン番号に基いてパッケージを管理します。

$ git tag 0.3.1
$ git push --tags
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:monmonmon/jquery.narrows.git
 * [new tag]         0.3.1 -> 0.3.1

バージョン 0.3.1 がリリースされました。

3. bower register

さていよいよ、ライブラリをレジストリへ登録します。コマンドの書式は

bower register <my-package-name> <git-endpoint>

です。

$ bower register jquery.narrows git@github.com:monmonmon/jquery.narrows.git
bower                          convert Converted git@github.com:monmonmon/jquery.narrows.git to git://github.com/monmonmon/jquery.narrows.git
bower jquery.narrows#*         resolve git://github.com/monmonmon/jquery.narrows.git#*
bower jquery.narrows#*        download https://github.com/monmonmon/jquery.narrows/archive/0.3.1.tar.gz
bower jquery.narrows#*         extract archive.tar.gz
bower jquery.narrows#*        resolved git://github.com/monmonmon/jquery.narrows.git#0.3.1
[?] Registering a package will make it installable via the registry (https://bower.herokuapp.com), continue? (Y/n)
bower jquery.narrows          register git://github.com/monmonmon/jquery.narrows.git

Package jquery.narrows registered successfully!
All valid semver tags on git://github.com/monmonmon/jquery.narrows.git will be available as versions.
To publish a new version, just release a valid semver tag.

Run bower info jquery.narrows to list the available versions.

ほんとに登録されたのか確認してみましょう。

$ bower info jquery.narrows
bower jquery.narrows#*          cached git://github.com/monmonmon/jquery.narrows.git#0.3.1
bower jquery.narrows#*        validate 0.3.1 against git://github.com/monmonmon/jquery.narrows.git#*

{
  name: 'jquery.narrows.js',
  version: '0.3.1',
  main: 'jquery.narrows.js',
  description: 'jQuery Hierselect Plugin',
  license: 'MIT',
  ignore: [
    '**/.*',
    '**/*.html',
    'Gruntfile.coffee',
    'node_modules',
    'README.md',
    'package.json',
    'lib',
    'spec'
  ],
  homepage: 'https://github.com/monmonmon/jquery.narrows'
}

Available versions:
  - 0.3.1

You can request info for a specific version with 'bower info jquery.narrows#<version>'

出た出た!

Bower components でも、検索フィールドに "jquery.narrows" って入力するとちゃんと表示されました。

試しに bower install してみる

今登録したライブラリがちゃんと bower install 出来るかも実験してみましょう。

$ bower install jquery.narrows#0.3.1
bower jquery.narrows#0.3.1      cached git://github.com/monmonmon/jquery.narrows.git#0.3.1
bower jquery.narrows#0.3.1    validate 0.3.1 against git://github.com/monmonmon/jquery.narrows.git#0.3.1
bower jquery.narrows#0.3.1     install jquery.narrows#0.3.1

jquery.narrows#0.3.1 bower_components/jquery.narrows

そしたらホラホラ!

$ ls -l bower_components/jquery.narrows
bower.json             jquery.narrows.js      jquery.narrows.min.js

ひゃっほい。

bowser.json の "ignore" をちゃんと書いたおかげで、余計なファイルを(ほぼ)含まずに js ファイルだけダウンロードすることが出来ました。(bower.json 自身だけ "ignore" に入れるのを忘れてたけど…笑)

というわけで

快適な bower ライフをお楽しみ下さい(とってつけた)

JSON 形式で設定ファイル書かせるの、やめてもらえません?

設定ファイルを JSON 形式で記述するライブラリやフレームワークって、

などなどいくつかあるけど(例が偏っててすみません)、

JSON って文法が結構デリケートなので、人間が(読む分にはいいけど)書くのには適してないと思うんですよね。

1. コメントが書けない!

JavaScript みたいにコメント書けません。

  ...
  "devDependencies": {
    //"grunt": "0.4.2", ちょっと退避
    "grunt": "0.4.1", // 古いバージョンに戻す
    "grunt-contrib-watch": "0.5.3",
    "grunt-contrib-uglify": "0.2.4"
  },
  ...

とか書けさえしたらどれだけ管理が楽になることか!

2. 連想配列やリストの要素を区切るカンマに注意する必要がある

↓は JSON としてはシンタックス違反ですが、どこが間違ってるか分かりますか?

  ...
  "devDependencies": {
    "grunt": "0.4.2",
    "grunt-contrib-watch": "0.5.3",
    "grunt-contrib-uglify": "0.2.4",
  },
  ...

答えは連想配列の最後がカンマで終わってるところです。正しくはこう。

  ...
  "devDependencies": {
    "grunt": "0.4.2",
    "grunt-contrib-watch": "0.5.3",
    "grunt-contrib-uglify": "0.2.4" // <- 最後に , があっちゃダメ
  },
  ...

これはリストでも同様です。

  ...
  "keywords": [
    "hoe",
    "hoehoe",
    "ehehe" // <- 最後に , があっちゃダメ
  ],
  ...

連想配列やリストに要素を追加したり並べ替えたりするのって頻繁にやるのに、その度にいちいちカンマに気を配るのって超めんどくさい。

もちろん、末尾のカンマだけでなく、要素と要素の間のカンマ忘れもありがちなミスですよね。

3. 文字列は必ずダブルクォートで囲まないといけない

JavaScript のオブジェクトリテラルでは

{
    "foo": "aaa", // ダブルクォートで囲んだり
    'bar': 'bbb', // シングルクォートで囲んだり
    buz: 'ccc',   // ていうか key はクォートで囲む必要すらない
}

って書けるけど、JSON では

  • 文字列はシングルクォートではなく、必ずダブルクォートで囲まないといけない
  • value だけでなく key も、文字列である場合はダブルクォートで囲まないといけない

ので、さっきの例は

{
    "foo": "aaa",
    "bar": "bbb",
    "buz": "ccc"
}

て書かないといけないです。

だからさー

設定ファイルは YAML 形式で書かせて下さいお願いします。。。

上で挙げた例すべて、YAML にするだけで一発解決ですよ。

ライブラリやフレームワークを管理してる方 or これから作るという方はどうぞご検討下さいm(_ _)m

jasmine + スクリーンショット作成サービスでWebアプリを複数ブラウザで一括動作確認!

この投稿は JavaScript - Client Side - Advent Calendar 2013 の13日目の参加記事です。

JavaScript のテスティングフレームワーク jasmine でテストを書いておくと、コードをいくらいじってもブラウザのリロード一発で動作確認できてそれだけでもステキです()。

でも更に、「スクリーンショット作成サービス」と組み合わせて利用すれば、複数の OS の複数のブラウザで一気にまとめて動作確認できてしまってステキングです。

このエントリでは、

  1. スクリーンショット作成サービスをいくつか紹介して、
  2. それら + jasmine による一括動作確認の方法について書いて、
  3. 最後に実際にやってみた例を紹介

します。

それではGO。

スクリーンショット作成サービス

を、2つ+αほど紹介。

1. browserstack.com の Screenshots

f:id:ymdsmn:20131211183553p:plain

動作確認したいページのURLを入力して、めぼしいブラウザを選択して(デフォルトで20ブラウザ選択済、最大25まで選択可)、画面一番下の "Generate screenshots" をクリックすると、

f:id:ymdsmn:20131211183558p:plain

こんな風にぞくぞくとスクリーンショットが送られてくる。

対応OS、対応ブラウザが盛りだくさんでステキ。なにより、スマホ対応なサービスってここしかないかも。

縦に長いウェブページも、画面の上から下までスクロールして撮ってくれます(確認した限り、多分全ブラウザで)。

欠点は、一度に25ブラウザまでしか選択できない点。(月額払えばこの制限はなくなる??)

また、無料で撮れるスクショ数はトータル100件までです。動作確認するブラウザを絞ってうまく利用しないといけない。Screenshots だけの利用であれば、月額$19でこのリミットはなくなるみたいです。

2. browsershots.org

f:id:ymdsmn:20131211190156p:plain

Linux, Windows, Mac, BSD に対応。

無料アカウント登録さえすれば、ブラウザ数の制限なしで、一気にまとめてスクショが撮れちゃうのがステキすぎる。アカウント登録なしでも1日あたり100ブラウザ?くらいまでなら多分利用可能。

LinuxBSD 対応ってのも、動作確認するサービスによっては重要でしょう。

撮ったスクショには有効期限があり、無料アカウント登録すれば30分、アカウントなしなら14分。

欠点としては、スクショを撮るホスト&ブラウザの提供を有志に頼っているため、対応ブラウザがちょこちょこ変動します。ついこないだは Mac の対応ブラウザは Safari が2つあったはずなのに、今みたら Mac の対応ブラウザ数ゼロになってた。。。

また、僕が見てる限り Mac の登録ブラウザ数が少ないです。(これはたまたまなのか、常にこうなのか?)

あと、スクロールの必要なページの場合でも、画面の1番上だけしか撮ってくれません。

とはいえ、Windows の対応ブラウザの多さと、無料でこれだけ多数のブラウザのスクショをまとめて一気に撮れるというのは強いです。

ちなみに、画面下の方のボタンで Windows ブラウザのみ全て選択、とか出来ます。

3. その他のサービス

screenshots.jp
月額払わないとスクショの撮れるブラウザが少なすぎるので試してないです(´・ω・`) 主要OSの主要ブラウザは対応しているようです。

browsershots.at
撮れるのは Windows VistaFirefox のみ(´・ω・`)

jasmine のテスト結果をまとめてスクリーンショット

さて、

これらスクリーンショット作成サービスで jasmine のテスト結果のスクショを撮れば、

色んな環境でズガッとまとめて動作確認出来ちゃうぜ!というのが今回のお話。

ブラボー!おお・・・ブラボー!!

f:id:ymdsmn:20131211185020j:plain

ただ、jasmine のテスト結果って画面一番下に表示されるから、1画面に収まるようなコンパクトなWEBアプリケーションでもない限り、スクショ一覧画面のサムネイルでは確認出来そうにないです。

いちいちサムネイルをポチポチクリックして、個別の画像を開いて、画像の一番下までスクロールして確認しないといけない。それってめんどくさい。(ていうか browsershots.org の場合は画面1番上しか撮れないのでそれすら無理。)

どうせなら、スクショ一覧画面でサムネイルを眺めるだけでテスト結果を確認したいですよね。

じゃー CSS or JavaScript で、jasmine のテスト結果を画面1番上に移動しちゃえばいいんじゃない?

jasmine テスト結果を画面1番上に表示させるには

jasmine-1.3.1 と jasmine-2.0.0-rc5 とで調べてみました。それぞれ、テスト結果を収めてるDOM要素がちょこっと異なります。

jasmine-1.3.1 の場合

テスト結果は id="HTMLReporter" な div に収められてます。

CSSでやるなら

#HTMLReporter {
  position: absolute;
  top: 0px;
  width: 100%;
  background-color: white;
}

jQuery でやるなら、

jasmineEnv.execute();

を呼んでる箇所の直後に

$('#HTMLReporter').remove().prependTo('body');

でオッケー。

jasmine-2.0.0-rc5 の場合

テスト結果は class="html-reporter" な div に収められてます。

CSSでやるなら

.html-reporter {
  position: absolute;
  top: 0px;
  width: 100%;
  background-color: white;
}

jQuery でやるなら、boot.js の下の方にテストをキックしてる箇所があるので、その直後に以下のように1行追加してやればいける。

  // ...
  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    htmlReporter.initialize();
    env.execute();                  // <-jasmineテスト実行
    // 以下を追加
    $('div.html-reporter').remove().prependTo('body');
  };
  // ...

実際にスクショを撮ってみた

拙作の jQuery プラグイン jquery.narrows.jsサンプルページ兼テストページ(の、テスト結果を一番上に移動したversion)で実験してみました。

まずは Screenshots

f:id:ymdsmn:20131212043922p:plain

サムネイルだけ眺めても大体分かりますよね?サムネイルのてっぺんに緑のバーが出ていれば成功、赤のバーならテスト失敗です。

  • Windows 7 の IE8(中段左から2番目)で赤いバーが出てるのが見える。テスト失敗してますがな。 元サイズの画像を開いて、エラーの内容も確認出来た。
  • Amazon Kindle Fire 2, Amazon Kindle Fire HD, Google Nexus 7 では、23個のテストすべて終了する前の時点のスクショが撮れてしまってた(そのため青っぽいバーが見えてます)。ひょっとして Kindle や Nexus は JavaScript の実行速度が遅いんでしょうか? iPhoneiPad はちゃんと成功してるのにな?
  • 一番最後の iPad 3rd (7.0)(びっくりマークのやつ)はタイムアウトした模様。ブラウザが多すぎると、最後の方のブラウザはこんな風にタイムアウトしてしまうっぽい。
  • IE6, IE7(上段右端、中段左端)だけ、テスト結果がどこにも表示されてませんでした…。JavaScript がオフなのか、jasmine が実行できてないのか、それともさっき追加した CSS がいけないのか、不明。

次に browsershots.orgWindows の全ブラウザのみ選択して、試してみました。

f:id:ymdsmn:20131211193108p:plain

105ものブラウザのスクショをリクエストしても粛々と任務遂行してくれるこの度量の深さ。ありがたいことです。(ここに表示してるのは一部のみです。)

  • MSIE 8.0, Firefox 1.0.8, Netscape 8.0.4, Netscape 7.1 でエラーを確認。 MSIE 8.0 でのエラーはさっきの結果と矛盾しません。それ以外のブラウザでのエラーは単に古すぎるためのようです。
  • いくつかのブラウザで、スクショ作成サーバの起動か何かに失敗していて、スクショが正常に撮れていませんでした(デスクトップにコマンドプロンプトだけ表示されてるやつとかです)。有志さん頼りな以上、こういうエラーはある程度仕方ないんでしょう。

こんな感じでした。なんだか色んなケースが確認出来てこれはいいサンプル(自画自賛)。

そして期せずして、jquery.narrows.js が IE8 で動作しないことが分かっちゃいました。直さなくちゃ…。僕Windowsマシン持ってないので、これ、そうそう気付けないバグですよ。

すごくない?(・ω・)-3

まとめ

みんな jasmine でテスト書こうよ。いいから書こうよ。

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 テストがとんでもなく遅くなっても心穏やかに開発出来るようになりました^^