概要
Jasmineを使ってJavaScriptのテストを書くチュートリアル。rubyで動くjasmine gemを利用する。理由は下記
- ウェブサーバーがついているのでプロダクションアプリを起動しなくてすむ
- Firefox(selenium webdriver)との連携が容易
testのスコープ
Jasmineでテストするのはあくまでユニットであり開発向けである。受け入れのテストとは分けて考えるべき
前準備
ruby1.9/2.0 とbundler
$ gem install bundler
2.0ではまったらトラブルシューティングの項を参照
準備
source :gemcutter
gem 'rake'
gem 'jasmine'
$ bundle instal --path=vendor
pathはお好みで指定するべし
ひな形の作成
$ bundle exec jasmine init
下記のようなファイルストラクチャができる
.
├── Gemfile
├── Rakefile
├── public
│ └── javascripts
│ ├── Player.js
│ └── Song.js
├── spec
│ └── javascripts
│ ├── PlayerSpec.js
│ ├── helpers
│ │ └── SpecHelper.js
│ └── support
│ └── jasmine.yml
jqueryとjasmine-jqueryを入れる
$ curl -O http://code.jquery.com/jquery-1.9.1.min.js
$ mv jquery-1.9.1.min.js public/javascripts/
$ curl -O https://github.com/velesin/jasmine-jquery/edit/master/lib/jasmine-jquery.js
$ mv jasmine-jquery.js spec/javascripts/helpers/
jasmine-jqueryを使うとfixturesやイベントのspyがやりやすくなる
試しに動かす
$ bundle exec rake jasmine
ウェブサーバーが立ち上がる。表示されたURLにブラウザでアクセスするとテストが実行され、全てグリーンになる。
Selenium-Webdriverを使う場合
$ bundle exec rake jasmine:ci
firefoxが立ち上がって、サンプルのtestが実行されて全てグリーンならOK
トラブルシューティング
rvmを使っててopensslがないエラー
$ brew install openssl
$ rvm requirements run
$ rvm uninstall 2.0.0-p0
$ rvm install 2.0.0-p0
Jasmine::YAMLなんてクラスないよってエラー
→ Rakefileとエラーしてるファイルの中でrequire 'yaml'と書いてしまう
その1 シンプルなクラス (というかオブジェクト)
実装コード
脱線: モジュールパターンと継承 :
JSのクラス設計はいくつか流派があるが今回はnewを使わないパターンで書く
var sample = {}; // namespace
sample.base = function(params) {
var _name;
if(typeof params === "object") {
_name = params.name;
}
function hello() {
return "Hello! I'm " + _name;
}
return { hello : hello };
};
sample.foo = function (params) {
var that = sample.base(params),
_moo,_woo;
function setWoo (woo) {
_woo = woo;
}
that.setWoo = setWoo;
function woo() {
return _woo;
}
that.woo = woo;
return that;
};
テスト
describe("sample.foo", function() {
var foo;
beforeEach(function() {
foo = sample.foo({name: "John"});
});
it("should say hello", function (){
var str = foo.hello();
expect(str).toEqual("Hello! I'm John");
});
if("should set/get woo", function () {
foo.setWoo("hoge");
expect(foo.woo()).toEqual("hoge");
});
});
その2: DOMイベントを使ったもの
例えばオンマウスであるdivを表示されるなど
実装
sample.ui = function (params) {
var that = sample.base(params);
function init() {
$("#foo").mouseover(function () {
$("#notice").show();
});
}
that.init = init;
return that;
};
フィクスチャー
spec/javascripts/fixtures/
下にテストで使うhtmlを置く
<div id="foo">FOO!</div>
<div id="notice" style="display:none">don't mouse over me!</div>
テスト
describe("ui",function (){
var ui;
beforeEach(function(){
loadFixtures("foo.html"); // fixtureをロード
ui = sample.ui();
ui.init();
});
it("should show notice",function() {
expect($("#notice")).not.toBeVisible(); // 表示されていない
$("#foo").trigger("mouseover");
expect($("#notice")).toBeVisible(); // 表示されている
})
});