Jasmineとguard-livereloadでJavaScriptのTDD環境を作る
Ruby(Rack + bundler)のwebアプリケーションでJavaScript部分をTDDで開発する環境を整えてみたので、作業メモを晒してみる。
今回はブラウザを使ったテストなので、GUI環境上に構築していく。
環境
- Mac OS X 10.7.4
- Ruby 1.9.3-p0
- rvm 1.9.2
- Xcode 4.3.2
Jasmineの準備
インストール
- Gemfile
gem "jasmine", :group => "test"
$ bundle install
イニシャライズ
$ bundle exec jasmine init
サンプルとなるJavaScriptとテストケースが自動生成される。
$ tree public/javascripts/ spec/javascripts/
public/javascripts/
├── Player.js
└── Song.js
spec/javascripts/
├── PlayerSpec.js
├── helpers
│ └── SpecHelper.js
└── support
└── jasmine.yml
RakefileにもJasmineのタスクが追加される。
- Rakefile
begin
require 'jasmine'
load 'jasmine/tasks/jasmine.rake'
rescue LoadError
task :jasmine do
abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
end
end
動作確認
rake jasmineを実行すると、8888番ポートでWEBrickが起動する。
$ bundle exec rake jasmine
your tests are here:
http://localhost:8888/
[2012-05-24 11:11:35] INFO WEBrick 1.3.1
[2012-05-24 11:11:35] INFO ruby 1.9.3 (2012-04-20) [x86_64-darwin11.3.0]
[2012-05-24 11:11:35] INFO WEBrick::HTTPServer#start: pid=16256 port=8888
ブラウザで http://localhost:8888/
にアクセスすると、サンプルとして用意されたPlayerSpec.jsに書かれたテストケースが走り、Player.jsをテストした結果を表示する。
guard-livereloadの準備
いちいちブラウザをリロードするのは面倒なので、guard-livereloadを使ってファイルの変更を監視し検知したらブラウザを自動リロードする、という仕組みも準備してみる。
インストール
- Gemfile
gem 'guard-livereload', :group => "test"
% bundle install
# (snip)
make
compiling binder.cpp
make: g++-4.2: No such file or directory
# (snip)
g++-4.2
がないというエラーが出たので乱暴に解決。 /usr/bin/g++-4.2
を /usr/bin/g++
のSymLinkとして作成する。
% which g++-4.2
g++-4.2 not found
% which g++
/usr/bin/g++
% sudo ln -s /usr/bin/g++ /usr/bin/g++-4.2
% which g++-4.2
/usr/bin/g++-4.2
続き。
% bundle exec guard init livereload
Writing new Guardfile to /{project_root}/Guardfile
livereload guard added to Guardfile, feel free to edit it
変更を監視するファイルの設定
アプリケーションのルートにGuardfileが生成されている。
- Guardfile
Jasmineに関連するファイルだけを監視対象にする。
guard 'livereload' do
watch(%r{public/.+\.js})
watch(%r{spec/javascripts/.+\.js})
end
実はこのままだと「JasmineによるTDD」はうまく動かない(後述)。
ブラウザエクステンションをインストール
LiveReload 1.xはDeprecatedらしいが、LiveReload 2は$9.99なのでとりあえず見送り。旧ドキュメントを参考に、利用するブラウザのエクステンションをインストールしておく。
https://github.com/mockko/livereload/blob/master/README-old.md
guard-livereloadを起動
% bundle exec guard
Guard could not detect any of the supported notification libraries.
Guard is now watching at '/{project_root}/'
LiveReload 1.6 is waiting for a browser to connect.
最初の行が気になるが、まずはLiveReloadがブラウザの監視を始めたようだ。
Safariの場合は
% bundle exec rake jasmine
でJasmineを起動しておいてブラウザで http://localhost:8888/ にアクセス。ページを右クリックして「Enable LiveReload」を選ぶ。
Browser connected.
Browser URL: http://localhost:8888/
リロードされない場合の対処
これでJavaScriptファイルが更新されるとブラウザがリロードされるはず。しかし別のターミナルから…
% touch path/to/your.js
などとすると、guardのコンソールに…
Reloading browser: path/to/your.js
とは出るのだが、ブラウザはリロードされない。
livereloadのREADMEによると…
# reload the whole page when .js changes
config.apply_js_live = false
apply_js_liveをfalseに設定すれば、JSの更新でページ全体をリロードしてくれるらしい。trueの場合は更新されたJavaScriptだけをリロードするので、Jasmineのテストは走らない。
この設定はGuardfileの引数として記述する、とドキュメントに書いてある。
Available options:
(snip)
:apply_js_live => false # default true
ということでGuardfileを書き換えて、guardを再起動する。
guard 'livereload', :apply_js_live => false do
watch(%r{public/.+\.js})
watch(%r{spec/javascripts/.+\.js})
end
% touch path/to/your.js
ブラウザが自動でリロードされただろうか。
まとめとLinks
今までずっと先送りにしてきたJavaScriptの単体テスト環境をやっと整えた。次はCIに組み込むべくjasmine-headless-webkitを導入したい。