Slide 1

Slide 1 text

+BWB4DSJQUϑϩϯτΤϯυ ։ൃͷࡢࠓ !OBPZB@JUP

Slide 2

Slide 2 text

͜Μʹͪ͸

Slide 3

Slide 3 text

࿩ͷྲྀΕ •  )5.-ΞϓϦέʔγϣϯΞηϯϒϥ •  ˢΛݟΔͱ+4։ൃͷτϨϯυ͕Θ͔Δ •  .7˓ϑϨʔϜϫʔΫ •  ςετ •  ·ͱΊϑϩϯτΤϯυ։ൃ࣮ࡍͷͱ͜Ζ

Slide 4

Slide 4 text

ΞϓϦέʔγϣϯαΠτΞηϯϒϥ ϑϩϯτΤϯυΞϓϦέʔγϣϯ੩తαΠτͷ ఆ൪ΞηοτΛ·ͱΊͯηοτΞοϓ $  middleman  init  -­‐–template=slim

Slide 5

Slide 5 text

.JEEMFNBOͰͰ͖ͯ·͢

Slide 6

Slide 6 text

˓˓Ξηϯϒϥ •  NBTN HBT •  αΠτΞηϯϒϥ – .JEEMFNBO •  ελςΟοΫαΠτδΣωϨʔλ •  ΞϓϦέʔγϣϯΞηϯϒϥ – :FPNBO #SVODIJP •  +BWB4DSJQUΞϓϦέʔγϣϯʹൺॏ

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

ZPXFCBQQ

Slide 10

Slide 10 text

$  yo  webapp   $  grunt  server   $  grunt  test   $  grunt  build  

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

:FPNBOHFOFSBUPSXFCBQQ •  (SVOUpMFKT •  CPXFSSD •  #PPUTUSBQGPS4BTT •  3FRVJSF+4 •  .PEFSOJ[S • 

Slide 13

Slide 13 text

ΞϓϦέʔγϣϯΞηϯϒϥͷ࣮ࡍ •  ։ൃ΍ͬͯΔͱͦͷ͏ͪඞཁʹͳΔಓ۩͕ ೖ͍ͬͯΔ – ϕετɾϓϥΫςΟε •  ͢ͳΘͪߏ੒͔ΒτϨϯυ͕ݟ͑Δ

Slide 14

Slide 14 text

:FPNBOͷߏ੒ཁૉ •  (SVOUλεΫϥϯφʔ •  #PXFSύοέʔδ؅ཧ •  :P4DB⒎PME Ξηοτͷੜ੒

Slide 15

Slide 15 text

(SVOU

Slide 16

Slide 16 text

(SVOUͬͯ •  /PEFKTϕʔεͷλεΫϥϯφʔ – $P⒎FF΍4BTTΛίϯύΠϧ͢Δ – ϛχϑΝΠ͢Δ – ಈ࡞֬ೝ༻ͷ)551αʔόʔ্ཱͪ͛Δ – -JWF3FMPBEͰߋ৽ʹ߹Θͤͯϒϥ΢βΛࣗ ಈͰϦϩʔυ͢Δ – σϓϩΠ༻ͷ֤छλεΫΛ·ͱΊ࣮ͯߦ͢Δ

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

(SVOUʹ͍ͭͯৄ͘͠͸ŋŋŋ ൃചͷ8%#13&44Λ଴ͯ

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

#PXFS •  ϥΠϒϥϦͷόʔδϣϯɾґଘؔ܎؅ཧ – ཁ͸ϑϩϯτΤϯυΞϓϦ༻ͷ#VOEMFS $  cat  bower.json   {      "name":  "myapp",      "version":  "0.0.0",      "dependencies":  {          "sass-­‐bootstrap":  "~3.0.0",          "requirejs":  "~2.1.8",          "modernizr":  "~2.6.2",          "jquery":  "~1.10.2"      },      "devDependencies":  {}   }   $  bower  install

Slide 21

Slide 21 text

/PEFKT ŋŋŋͱ͍͏Θ͚Ͱ࠷ۙͷϑϩϯτΤϯυ։ൃ ͸/PEFKTʹΑͬͯࢧ͑ΒΕ͍ͯ·͢

Slide 22

Slide 22 text

:FPNBOHFOFSBUPS •  ZPHFOFSBUPSOBNF •  ͍Ζ͍Ζ͋Δ

Slide 23

Slide 23 text

"OHVMBS+4ͷ͕Ұ൪ਓؾ

Slide 24

Slide 24 text

HFOFSBUPSBOHVMBS •  "OHVMBS+4.7ϑϨʔϜϫʔΫ •  ςετؔ࿈ –  LBSNBϦϞʔτςετϥϯφʔ –  +BTNJOFςεςΟϯάϑϨʔϜϫʔΫ –  1IBOUPN+4ϔουϨεϒϥ΢β –  USBWJTZNMܧଓతΠϯςάϨʔγϣϯ •  (SVOUpMFKT •  CPXFSSD •  KTIJOUSD •  FEJUPSDPOpH

Slide 25

Slide 25 text

ͳΜ͔͍Ζ͍Ζ͋Γ·͢Ͷ

Slide 26

Slide 26 text

.7˓ϑϨʔϜϫʔΫ ͔Βݟ͍͖ͯ·͠ΐ͏

Slide 27

Slide 27 text

.7˓ϑϨʔϜϫʔΫ h"p://www.slideshare.net/OmasaYusaku/angular-­‐js-­‐orbackbonejs

Slide 28

Slide 28 text

h"p://wazanova.jp/post/63527486760/ruby-­‐on-­‐rails-­‐angularjs-­‐node-­‐js

Slide 29

Slide 29 text

JO 0DU ͋Μ·Γ ؾʹ͠ͳ͍

Slide 30

Slide 30 text

ͳͥ.7˓ϑϨʔϜϫʔΫ •  γϯάϧϖʔδΞϓϦέʔγϣϯ •  K2VFSZ஍ࠈ •  όϦσʔγϣϯ •  QVTI4UBUF

Slide 31

Slide 31 text

σʔλόΠϯσΟϯά͕ॏཁ ˞ݸਓతݟղͰ͋ΓࣾΛ୅ද͢ΔҎԼུ

Slide 32

Slide 32 text

ཁ͸ɺ͜Ε͕͍ͨ͠ Model View View Ϟσϧ͕มߋ͞ΕͨΒŋŋŋ ը໘Λߋ৽ ը໘Λߋ৽ ੲͱҧͬͯ+4Ͱը໘͙Γ͙Γߋ৽͢ΔΑ͏ʹͳͬͨ͠ Πϕϯτ

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

#BDLCPOFKT.PEFMͱ 7JFXͷόΠϯυ class  TagsView  extends  Backbone.View      tagName:  'ul'        initialize:  ()  -­‐>          @listenTo  @collection,  'add',  @addTag        addTag:  (tag)  -­‐>          tagView  =  new  TagView  model:tag          @$el.append  tagView.render().el        render:          @collection.each  (tag)  =>  @addTag  tag          return  @     #  Tags  extends  Backbone.Collection   tags  =  new  Tags  []   tagsView  =  new  TagsView  collection:tags     $('#tags-­‐view').html  tagsView.render().el

Slide 35

Slide 35 text

TagsView   Backbone.View Tags   Backbone.Collection ೖྗΠϕϯτ Ϟσϧߋ৽Πϕϯτ

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

"OHVMBS+4૒ํ޲σʔλόΠ ϯσΟϯά
         
  •            {{todo.title}}      
  •  
var  controller  =  app.controller('TodoCtrl',  function  ($scope,  todo_list)  {      $scope.todo_list  =  todo_list;      $scope.addTodo  =  function()  {          $scope.todo_list.push(                {  "title":  $scope.todo.title,  "state":  $scope.todo.state  }            );      };       });  

Slide 38

Slide 38 text

  •      {{todo.title}}  
  • $scope.   todo_list όΠϯυ

    Slide 39

    Slide 39 text

    +4.7˓ϑϨʔϜϫʔΫ •  ݸਓతͳݟཱͯͰ͸ŋŋŋ –  ʮ.ˠ7΁ͷ௨஌ʯͷύλʔϯΛओ࣠ʹपลΛݻΊͨ΋ͷ •  όΠϯσΟϯάΛ͠΍͘͢㱺ΞϓϦέʔγϣϯߏ଄Խ •  ͦͷ΄͔ศརػೳ –  ϧʔςΟϯά –  ςϯϓϨʔτ –  όϦσʔγϣϯ –  ը໘ભҠ •  ΑͬͯɺσʔλϞσϧͷߋ৽ʹରͯ͠ը໘͕Ͳͷఔ౓ͲͷΑ ͏ʹ࿈ಈ͢Δඞཁ͕͋Δ͔ɺͱ͍͏ࢹ఺Ͱબఆ͢Δͱྑ͍

    Slide 40

    Slide 40 text

    ૄ݁߹Λࢧ͑Δٕज़ •  #BDLCPOFKT –  0CTFSWFSʹΑΔ.PEFM7JFXͷ෼཭ –  #BDLCPOFKTͷ௨஌ύλʔϯ •  "OHVMBS+4 –  ૒ํ޲σʔλόΠϯσΟϯά –  %FQFOEFODZ*OKFDUJPO –  ϑϨʔϜϫʔΫͷڧΊͷ੍໿ •  &NCFSKT –  ͳΜ͔σʔλόΠϯσΟϯάपΓ͕͍͚ͯΔΒ͍͠ •  0CKFDUPCTFSWF –  J04ͷ,70Έ͍ͨͳͷɻ࣍ੈ୅+BWB4DSJQU –  ݱঢ়Ͳ͏ͳͬͯΔΜͰ͠ΐ͏

    Slide 41

    Slide 41 text

    ςετ͠қ͘ͳͬͪΌ͍·ͨ͠ ͱ͜ΖͰΞϓϦέʔγϣϯߏ଄ԽʹΑͬͯ

    Slide 42

    Slide 42 text

    ͦ͏ͩɺ +4΋ ςετ͠Α͏

    Slide 43

    Slide 43 text

    HFOFSBUPSBOHVMBS •  "OHVMBS+4.7ϑϨʔϜϫʔΫ •  ςετؔ࿈ –  LBSNBϦϞʔτςετϥϯφʔ –  +BTNJOFςεςΟϯάϑϨʔϜϫʔΫ –  1IBOUPN+4ϔουϨεϒϥ΢β –  USBWJTZNMܧଓతΠϯςάϨʔγϣϯ •  (SVOUpMFKT •  CPXFSSD •  KTIJOUSD •  FEJUPSDPOpH

    Slide 44

    Slide 44 text

    ϞοΫ   ϥΠϒϥϦ Ξαʔγϣϯ   ϥΠϒϥϦ ςεςΟϯά   ϑϨʔϜϫʔΫ ϦϞʔτ   ςετϥϯφʔ ࣮ߦ   ؀ڥ Jasmine Sinon.JS QUnit,   JsUnit expect.js   Chai Mocha   Testem,  Karma JsTestDriver   Buster.JS ࣮ϒϥ΢β   IE,  Chrome,   FirefoxͳͲ   ϔουϨεϒϥ΢β   PhantomJS   ϒϥ΢βγϛϡϨʔλ   Node.js  +  jsdom   Rhino  +  Envjs   ʰ8%#13&447P+BWB4DSJQU׆༻࠷લઢୈճʱΑΓ

    Slide 45

    Slide 45 text

    ϞοΫ   ϥΠϒϥϦ Ξαʔγϣϯ   ϥΠϒϥϦ ςεςΟϯά   ϑϨʔϜϫʔΫ ϦϞʔτ   ςετϥϯφʔ ࣮ߦ   ؀ڥ Jasmine Sinon.JS QUnit,   JsUnit expect.js   Chai Mocha   Testem  /  Karma JsTestDriver   Buster.JS ࣮ϒϥ΢β   IE,  Chrome,   FirefoxͳͲ   ϔουϨεϒϥ΢β   PhantomJS   ϒϥ΢βγϛϡϨʔλ   Node.js  +  jsdom   Rhino  +  Envjs  

    Slide 46

    Slide 46 text

    ϞοΫ   ϥΠϒϥϦ Ξαʔγϣϯ   ϥΠϒϥϦ ςεςΟϯά   ϑϨʔϜϫʔΫ ϦϞʔτ   ςετϥϯφʔ ࣮ߦ   ؀ڥ Jasmine Sinon.JS QUnit,   JsUnit expect.js   Chai Mocha   Testem  /  Karma JsTestDriver   Buster.JS ࣮ϒϥ΢β   IE,  Chrome,   FirefoxͳͲ   ϔουϨεϒϥ΢β   PhantomJS   ϒϥ΢βγϛϡϨʔλ   Node.js  +  jsdom   Rhino  +  Envjs  

    Slide 47

    Slide 47 text

    ςεςΟϯάϑϨʔϜϫʔΫ •  #%%ελΠϧ͕ਓؾ Լ͸+BTNJOF describe('Controller:  TodoCtrl',  function  ()  {      beforeEach(module('angularApp'));      var  TodoCtrl,  scope;        beforeEach(inject(function($controller,  $rootScope)  {          scope  =  $rootScope.$new();          TodoCtrl  =  $controller('TodoCtrl',  {              $scope:  scope          });      }));        it('should  attach  a  list  of  todos  to  the  scope',  function  ()  {          expect(scope.todo_list.length).toBe(1);      });   });  

    Slide 48

    Slide 48 text

    +BTNJOF .PDIB •  શ෦ೖΓͷ+BTNJOF •  BHOPTUJDͳ.PDIB – ϞοΫελϒ4JOPO+4 – ΞαʔγϣϯFYQFDUKTɺ$IBJ ࣗ෼͸NPDIBFYQFDUKT4JOPO+4Λ࢖ͬͯ·͢

    Slide 49

    Slide 49 text

    ϦϞʔτςετϥϯφʔ •  ίʔυߋ৽ͷͨͼɺ࣮ϒϥ΢β΍ 1IBOUPN+4Ͱςετ – LBSNB چ5FTUBDVMBS – UFTUFN ͲͪΒ΋/PEFKTϕʔεͰಉ͡Α͏ͳػೳΛఏڙɻ5FTUBDVMBS͸ͦ ΋ͦ΋"OHVMBS+4ͷͨΊʹ࡞ΒΕͨͷͰɺ"OHVMBS+4ͱηοτͰ ࢖ΘΕΔ͜ͱ͕ଟ͍ɺ͔΋ɻ

    Slide 50

    Slide 50 text

    LBSNB

    Slide 51

    Slide 51 text

    UFTUFN

    Slide 52

    Slide 52 text

    LBSNB5SBWJT$*

    Slide 53

    Slide 53 text

    USBWJTZNM language:  node_js   node_js:      -­‐  '0.8'      -­‐  '0.10'   before_script:      -­‐  'npm  install  -­‐g  bower  grunt-­‐cli'      -­‐  'bower  install'      -­‐  export  DISPLAY=:99.0      -­‐  sh  -­‐e  /etc/init.d/xvfb  start   script:      -­‐  karma  start  -­‐-­‐reporters  dots  -­‐-­‐browsers  Firefox,PhantomJS   -­‐-­‐single-­‐run  

    Slide 54

    Slide 54 text

    LBSNBJTUBOCVM •  LBSNB͸JTUBOCVM࿈ܞͰΧόϨοδϨϙʔτ Λ؆୯ʹ௥ՃͰ͖Δ

    Slide 55

    Slide 55 text

    Ϣχοτςετͱ&&ςετ •  Ϣχοτςετ – \LBSNB UFTUFN^\+BTNJOF .PDIB^ – ϑϨʔϜϫʔΫͷ͓͔͛ͰϞσϧͷςετॻ ͚Δ͠ॻ͘ɻ7JFX͸૬มΘΒͣগ͠೉͍͠ Ͱ͢Ͷ •  &&ςετ – ŋŋŋ

    Slide 56

    Slide 56 text

    No content

    Slide 57

    Slide 57 text

    +4ͷ&&ςετ΋ׂͱΧ δϡΞϧʹॻ͘Έ͍ͨͰ͢ ೝࣝΛվΊ·ͨ͠ŋŋŋ

    Slide 58

    Slide 58 text

    &&ςετ •  LBSNBԿ͔ – "OHVMBS+4ŋŋŋ&&ςετϑϨʔϜϫʔΫ Λ಺แ •  $BTQFS+4 – 1IBOUPN+4ͷάουϥούʔ – +4ͷ&&ςετ͕+4͚ͩͰ؆୯ʹॻ͚Δŋŋŋ •  ςετϑϨʔϜϫʔΫɺΞαʔγϣϯ΋ఏڙͯ͠ ͍Δ •  ϩάΠϯͷ͋ΔςετͳͲ΋؆୯

    Slide 59

    Slide 59 text

    $BTQFS+4 casper  =  require('casper').create()     ##  amazlet  top  page   casper.start  'http://app.amazlet.com/',  ()  -­‐>      @echo  @getCurrentUrl()      @echo  @getTitle()      @fill  'form',  keyword:  casper.cli.args[0]      @click  'form  input[type="submit"]'     ##  search  result   casper.then  -­‐>      @echo  @getCurrentUrl()      #  click  on  1st  result  link      @click  'a.minibutton'     ##  get  affiliate  tag  for  first  item   casper.then  -­‐>      @echo  @getCurrentUrl()      @echo  @evaluate  -­‐>          document.getElementById('standard').value     do  casper.run

    Slide 60

    Slide 60 text

    $BTQFS+4Ͱ&&ςετ casper.test.begin  'トップページから検索して貼り付けHTMLを取得',  7,  (test)  -­‐>      casper.start  'http://app.amazlet.com/',  -­‐>          test.assertHttpStatus  200          test.assertTitleMatch  /^amazlet/,  "タイトル文字列が期待通り"          test.assertExists  'form',  "メインフォームがある"            @fill  'form',  keyword:  "chef  solo"          @click  'form  input[type="submit"]'        casper.then  -­‐>          test.assertHttpStatus  200          test.assertExists  'p.title',  '検索結果が一つ以上ある'            @click  'a.minibutton'        casper.then  -­‐>          test.assertHttpStatus  200          result  =  @evaluate  -­‐>  document.getElementById('standard').value          test.assertMatch  result,  /^
             do  test.done  

    Slide 61

    Slide 61 text

    No content

    Slide 62

    Slide 62 text

    $BTQFS+4Ͱ$* •  $BTQFS+4Ͱ΋$*Մೳ – $BTQFS+4ࣗ৴͸1IBOUPN+4ʹ͔͠ґଘ ͍ͯ͠ͳ͍ – 5SBWJT$*ʹ΋1IBOUPN+4͸ೖͬͯΔ – ΋ͪΖΜ+FOLJOTͰ΋0,

    Slide 63

    Slide 63 text

    ʮͰ΋Πϯετʔϧͱ͔໘౗ͳΜ Ͱ͠ΐ͏ ʯ $  brew  install  casperjs  -­‐-­‐ devel

    Slide 64

    Slide 64 text

    ࣮ײ •  :FPNBO৔߹ʹΑΔ •  (SVOUඞਢ •  #PXFSSFRVJSFKT৔߹ʹΑΔ •  ϑϨʔϜϫʔΫجຊ࢖͏ •  ςετ – ϦϞʔτςετϥϯφʔඞਢ – Ϣχοτςετ.पΓඞਢ •  .͕ෳࡶͰͳ͍৔߹͸&&͋Ε͹ͦΕͰ͍͍͔ – $*ඞਢ – &&ςετ؆୯ʹͳͬͨ͠ॻ͍ͨํ͕ಘ

    Slide 65

    Slide 65 text

    ·ͱΊ •  :FPNBO΍#VSODIJP͔ΒτϨϯυ •  /PEFKT͕ࢧ͑Δ •  ϑϨʔϜϫʔΫ͸σʔλόΠϯσΟϯάॏཁ •  +4΋ςετΛॻ͍ͯ$*͢Δ •  &&ςετ΋ݱ࣮తʹ –  ͜Μͳʹ؆୯ʹॻ͚Δͱ͸ŋŋŋ •  ϑϩϯτΤϯυ։ൃ͸੒ख़ظʹ –  ͍ͣΕͷπʔϧ؀ڥ΋೉ͳ͘࢖͑·͢