BACKBONE.JSにJasmineでテストコード書いてみた (LT資料)

2,848 views
2,694 views

Published on

BACKBONE.JSのModelに対して
JasmineとSinon.jsでテストを記述してみました。

間違いとかもっとこうした方が良いとかございましたら
@itokami1123まで教えてください!

2013/10/16(水) JSテスト勉強会@福岡 第1回 LT資料

----------------------------------------------------------------
Web制作向け無料写真素材/ぱくたそ (http://www.pakutaso.com)の写真を使用しました。
ありがとうございます。

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,848
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

BACKBONE.JSにJasmineでテストコード書いてみた (LT資料)

  1. 1. + Sinon.JS BACKBONE.JSにJasmineでテストコード書いてみた 2013/10/16(水) JSテスト勉強会@福岡 第1回 LT資料 写真はWeb制作向け無料写真素材/ぱくたそ http://www.pakutaso.comを使ってます。ありがとうございます。 13年10月16日水曜日
  2. 2. 自己紹介です ======== - twitter: @itokami1123 - 下請けやら派遣やらなんやら開発してます - JavaEE6と会計の勉強はじめました。 - 目標  業務系Webアプリの世界にもJavaScriptMVCを! コミュニティの力で福岡を一つにして  景気をよくする!(一生福岡でPGしたいっす)   13年10月16日水曜日
  3. 3. 今日の資料おかしいと思ったら 途中でビシバシ 突っ込んでね! (優しく) 13年10月16日水曜日
  4. 4. BACKBONE.JSで書いていると ソースが Model View に分かれます! 13年10月16日水曜日
  5. 5. と言う事は 時間がなくても Modelだけ テストコードかけるかも!? 13年10月16日水曜日
  6. 6. ↑のような画面を作ってるときの... 13年10月16日水曜日
  7. 7. ↑の一行明細のModelデータをテスト! 13年10月16日水曜日
  8. 8. メニュー表項目(1行分データ)Modelに var MenuItem = Backbone.Model.extend({ defaults: function(){ return { name: "", price: 0 , selected: false }; }, toggleSelected: function(){ var putData={"selected": !this.get("selected")}; this.save( putData, {wait: true}); } }); 13年10月16日水曜日
  9. 9. オブジェクト生成のテスト! var MenuItem = Backbone.Model.extend({ defaults: function(){ return { name: "", price: 0 , selected: false }; describe ("MenuItem", function() { var menuItem; beforeEach(function() { menuItem = new MenuItem(); }); }, afterEach(function() { toggleSelected: function(){ menuItem.destroy(); menuItem = null; var putData={"selected": !this.get("selected")}; }); this.save( putData); } describe( "オブジェクト生成時", function() { it( "初期値としてデフォルト値が設定される事", function() { }); expect(menuItem).toBeDefined(); expect(menuItem.get("name")).toBe(""); expect(menuItem.get("price")).toBe(0); expect(menuItem.get("selected")).toBe(false); }); }); }); 13年10月16日水曜日
  10. 10. オブジェクト生成時テストはグリーン!やったね! var MenuItem = Backbone.Model.extend({ defaults: function(){ return { name: "", price: 0 , selected: false }; describe ("MenuItem", function() { var menuItem; beforeEach(function() { menuItem = new MenuItem(); }); }, afterEach(function() { toggleSelected: function(){ menuItem.destroy(); menuItem = null; var putData={"selected": !this.get("selected")}; }); this.save( putData); } describe( "オブジェクト生成時", function() { it( "初期値としてデフォルト値が設定される事", function() { }); expect(menuItem).toBeDefined(); expect(menuItem.get("name")).toBe(""); expect(menuItem.get("price")).toBe(0); expect(menuItem.get("selected")).toBe(false); }); }); }); 13年10月16日水曜日
  11. 11. 次はメニューボタンのON/OFFの切り替えテスト! var MenuItem = Backbone.Model.extend({ ・・・省略・・・ }); toggleSelected: function(){ var putData={ "selected": !this.get("selected") }; this.save( putData, {wait: true}); } describe ("MenuItem", function() { var menuItem; beforeEach(function() { menuItem = new MenuItem(); }); afterEach(function() { menuItem.destroy(); menuItem = null; }); describe( "メニュー選択時", function(){ it( "トグル選択される事", function(){ expect(menuItem).toBeDefined(); expect(menuItem.get("selected")).toBeFalsy(); menuItem.toggleSelected(); expect(menuItem.get("selected")).toBeTrusy(); }); }); }); 13年10月16日水曜日
  12. 12. ぐぁぁぁぁぁ...、Σ( ` o ‘ var MenuItem = Backbone.Model.extend({ ・・・省略・・・ }); toggleSelected: function(){ var putData={ "selected": !this.get("selected") }; this.save( putData, {wait: true}); } describe ("MenuItem", function() { var menuItem; beforeEach(function() { menuItem = new MenuItem(); }); afterEach(function() { menuItem.destroy(); menuItem = null; }); describe( "メニュー選択時", function(){ it( "トグル選択される事", function(){ expect(menuItem).toBeDefined(); expect(menuItem.get("selected")).toBeFalsy(); menuItem.toggleSelected(); expect(menuItem.get("selected")).toBeTrusy(); }); }); }); 13年10月16日水曜日
  13. 13. な、なんで...Σ( ` o ‘ var MenuItem = Backbone.Model.extend({ ・・・省略・・・ }); toggleSelected: function(){ var putData={ "selected": !this.get("selected") }; this.save( putData, {wait: true}); } describe ("MenuItem", function() { var menuItem; サーバにPUT更新するリクエストを単体で beforeEach(function() { 動作させる必要がある作りでした... menuItem = new MenuItem(); }); afterEach(function() { menuItem.destroy(); menuItem = null; }); describe( "メニュー選択時", function(){ it( "トグル選択される事", function(){ expect(menuItem).toBeDefined(); expect(menuItem.get("selected")).toBeFalsy(); menuItem.toggleSelected(); expect(menuItem.get("selected")).toBeTrusy(); }); }); }); 13年10月16日水曜日
  14. 14. そこでSinon.JS使います! http://sinonjs.org/ 13年10月16日水曜日
  15. 15. テストコードを書き直しました〜。 var MenuItem = Backbone.Model.extend({ ・・・省略・・・ }); describe ("MenuItem", function() { describe( "メニュー選択時", function(){ toggleSelected: function(){ var putData={ "selected": !this.get("selected") }; this.save( putData, {wait: true}); } Sinon.jsの機能で ダミーの応答を返す! ダミーで返す値を 細かく指定できます! }); 13年10月16日水曜日 var menuItem,server; beforeEach( function(){ menuItem = new MenuItem({ "id": 1, "name": "test", "price": 100, "selected": false }); menuItem.url = "/unitTestUrl"; server = sinon.fakeServer.create(); }); afterEach(function () { server.restore(); }); it( "トグル選択される事", function(){ expect(menuItem).toBeDefined(); expect(menuItem.get("selected")).toBeFalsy(); server.respondWith( "PUT","/unitTestUrl",[ 200, {"Content-Type": "application/json"}, '{"id":1,"name":"test","price":100,"selected":true}' ]); menuItem.toggleSelected(); server.respond(); expect(menuItem.get("selected")).toBeTruthy(); }); });
  16. 16. 次は↑の明細複数行のModelデータをテスト! 13年10月16日水曜日
  17. 17. 明細複数行Model(Collection)に var MenuList = Backbone.Collection.extend({ model: MenuItem, comparator: 'id' sumPrice: function(){ var sum = 0, selectedMenuItems = this.where({ selected:true }); _.each( selectedMenuItems, function( model){ sum += model.get( "price"); }); return sum; }, createMenu: function(name,price){ var menuItemData = { name:name, price:price, selected:false }; this.create(menuItemData, {wait: true}); }, }); 13年10月16日水曜日
  18. 18. 合計金額算出のテストケース追加! var MenuList = Backbone.Collection.extend({ model: MenuItem, comparator: 'id' sumPrice: function(){ var sum = 0, selectedMenuItems = this.where({ selected:true }); _.each( selectedMenuItems, function( model){ sum += model.get( "price"); }); return sum; }, createMenu: function(name,price){ describe ( "MenuList", function() { var menuItemData = { name:name, describe ( "選択メニュー合計金額算出", function() { price:price, selected:false it( "格納モデルの選択中より合計金額を算出する", function() { }; this.create(menuItemData, {wait: true}); var menuList = new MenuList([ }, { name:"a", price: 100, selected: true}, { name:"b", price: 200, selected: false}, }); { name:"c", price: 400, selected: true}, ]); expect( menuList.sumPrice()).toBe( 500); }); }); 13年10月16日水曜日 });
  19. 19. 合計金額算出のテストはOK(グリーン)!\(^o^)/ var MenuList = Backbone.Collection.extend({ model: MenuItem, comparator: 'id' sumPrice: function(){ var sum = 0, selectedMenuItems = this.where({ selected:true }); _.each( selectedMenuItems, function( model){ sum += model.get( "price"); }); return sum; }, createMenu: function(name,price){ describe ( "MenuList", function() { var menuItemData = { name:name, describe ( "選択メニュー合計金額算出", function() { price:price, selected:false it( "格納モデルの選択中より合計金額を算出する", function() { }; this.create(menuItemData, {wait: true}); var menuList = new MenuList([ }, { name:"a", price: 100, selected: true}, { name:"b", price: 200, selected: false}, }); { name:"c", price: 400, selected: true}, ]); expect( menuList.sumPrice()).toBe( 500); }); }); 13年10月16日水曜日 });
  20. 20. 次は新規メニュー登録のテストケース追加! var MenuList = Backbone.Collection.extend({ model: MenuItem, comparator: 'id' describe ( "MenuList", function() { // ・・・省略・・・ sumPrice: function(){ var sum = 0, describe( "新規メニュー表登録", function() { selectedMenuItems = this.where({ selected:true }); it( "サーバより返却された名称と金額が設定されること", function(){ _.each( selectedMenuItems, function( model){ sum += model.get( "price"); server = sinon.fakeServer.create(); }); var menuList = new MenuList(); return sum; menuList.url = "/unitTestUrl"; }, server.respondWith([ 200, {"Content-Type": "application/json"}, '{"id":123,"name":"sevNam", "price":1005,"selected":false}' createMenu: function(name,price){ var menuItemData = { name:name, price:price, selected:false }; ]); menuList.createMenu( 'test', 1000); server.respond(); this.create( menuItemData, {wait: true} ); expect( menuList.size()).toBe( 1); var model = menuList.get(123); expect( model.get("name") ).toBe( "sevNam"); expect( model.get("price") ).toBe( 1005); }, }); }); 13年10月16日水曜日 }); })
  21. 21. 新規メニュー表登録処理もOK(グリーン)! var MenuList = Backbone.Collection.extend({ model: MenuItem, comparator: 'id' describe ( "MenuList", function() { // ・・・省略・・・ sumPrice: function(){ var sum = 0, describe( "新規メニュー表登録", function() { selectedMenuItems = this.where({ selected:true }); it( "サーバより返却された名称と金額が設定されること", function(){ _.each( selectedMenuItems, function( model){ sum += model.get( "price"); server = sinon.fakeServer.create(); }); var menuList = new MenuList(); return sum; menuList.url = "/unitTestUrl"; }, server.respondWith([ 200, {"Content-Type": "application/json"}, '{"id":123,"name":"sevNam", "price":1005,"selected":false}' createMenu: function(name,price){ var menuItemData = { name:name, price:price, selected:false }; ]); menuList.createMenu( 'test', 1000); server.respond(); this.create( menuItemData, {wait: true} ); expect( menuList.size()).toBe( 1); var model = menuList.get(123); expect( model.get("name") ).toBe( "sevNam"); expect( model.get("price") ).toBe( 1005); }, }); }); 13年10月16日水曜日 }); })
  22. 22. まとめ 13年10月16日水曜日
  23. 23. まとめです ======== - Backbone.jsのように MV*にすれば  Modelのみのテストコードが書きやすい! まとめ - ModelからのAjax通信も  Sinon.jsのFakeServerを使えば  ユニットテストできる! 13年10月16日水曜日
  24. 24. 何か質問とか もっとこうした方が良いよとかありますか?? 13年10月16日水曜日
  25. 25. ご清聴ありがとうございました! 今日の資料で出てきたソースは以下で公開してます。 https://github.com/itokami1123dev/hamburger_shop_prj 13年10月16日水曜日

×