Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Testing Javascript with Jasmine

Slides from my Lonestar Ruby Conf 2011 presentation.

*** Video of presentation: http://confreaks.com/videos/2531-lsrc2011-testing-javascript-with-jasmine ***

Agenda:
- Briefly cover why you should unit test
- Discuss what Jasmine is and isn't
- Show syntax with comparisons to RSpec
- Jasmine with:
- Vanilla JavaScript
- Jasmine with jQuery
- Jasmine with Ruby (not Rails)
- Jasmine with Rails
- Evergreen
- capybara-webkit
- Where does CoffeeScript, node.js, etc. fit in?
- Other helpful libraries/Wrap-up

  • Soyez le premier à commenter

Testing Javascript with Jasmine

  1. 2. Testing JavaScript with Jasmine By: Tim Tyrrell
  2. 3. Tim Tyrrell @timtyrrell    
  3. 4. Agenda <ul><li>- Briefly cover why you should unit test </li></ul><ul><li>- Discuss what Jasmine is and isn't </li></ul><ul><li>- Show syntax with comparisons to RSpec </li></ul><ul><li>- Jasmine with: </li></ul><ul><li>    - Vanilla JavaScript </li></ul><ul><li>    - Jasmine with jQuery </li></ul><ul><li>    - Jasmine with Ruby (not Rails) </li></ul><ul><li>    - Jasmine with Rails </li></ul><ul><li>    - Evergreen </li></ul><ul><li>    - capybara-webkit </li></ul><ul><li>- Where does CoffeeScript, node.js, etc. fit in? </li></ul><ul><li>- Other helpful libraries/Wrap-up </li></ul>
  4. 5. Why are you talking about JavaScript at a  Ruby conference?
  5. 6. Why unit test JavaScript?
  6. 7. &quot;External tests don't help us with internal design&quot; @glv
  7. 8. &quot;There is only one way to go truly fast. Do the best job you can. Anything else is slower.&quot; @unclebobmartin http://twitter.com/#!/unclebobmartin/status/39438225869254656
  8. 10. What is Jasmine?
  9. 11. Why Jasmine?
  10. 12. Jasmine is not an integration testing framework.
  11. 13. RSpec vs. Jasmine: Structure #RSpec describe &quot;Calculate&quot; do      describe &quot;#add&quot; do          it &quot;should return the sum&quot; do              ...          end      end end //Jasmine describe &quot;Calculate&quot;, function(){      describe &quot;#Add&quot;, function(){          it &quot;should return the sum&quot;, function(){          ...          };      }); });
  12. 14. RSpec vs. Jasmine: Before/After #RSpec before(:each) do           @calc = Calculator.new  end    after(:each) do           @calc.reset  end //Jasmine var calc;  beforeEach(function(){     calc = new Calculator(); });    afterEach(function(){     calc.reset();  });
  13. 15. RSpec vs. Jasmine: Expectations # RSpec  it &quot;should return the sum&quot; do       calc = Calculator.new        calc.add(1,1).should == 2     calc.add(1,2).should_not == 2 #Use one expectation per 'it'! end   // Jasmine  it(&quot;should return the sum&quot;, function() {           var calc = new Calculator();       expect(calc.Add(1,1)).toEqual(2);     expect(calc.Add(1,2)).not.toEqual(2); //Use one expectation per 'it'!  });
  14. 16. Jasmine Matchers expect(x).toEqual(y)   expect(x).toBe(y);   expect(x).toMatch(pattern) expect(x).toBeDefined() expect(x).toBeNull();   expect(x).toBeTruthy(); expect(x).toBeFalsy(); expect(x).toContain(y); expect(x).toBeLessThan(y); expect(x).toBeGreaterThan(y); expect(fn).toThrow(e);
  15. 17. Custom Matchers <ul><li>#RSpec </li></ul><ul><li>Spec::Matchers.define :be_greater_than_zero do </li></ul><ul><li>  match do |actual| </li></ul><ul><li>    actual > 0 </li></ul><ul><li>  end </li></ul><ul><li>end </li></ul><ul><li>Spec::Matchers.define :be_zero_when_subtracting do </li></ul><ul><li>  match do |actual, number| </li></ul><ul><li>    (actual - number) == 0 </li></ul><ul><li>  end </li></ul><ul><li>end </li></ul>
  16. 18. Custom Matchers <ul><li>// Jasmine </li></ul><ul><li>beforeEach(function() { </li></ul><ul><li>  this.addMatchers({ </li></ul><ul><li>    toBeGreaterThanZero: function() { </li></ul><ul><li>      return this.actual > 0; </li></ul><ul><li>    } </li></ul><ul><li>  }), </li></ul><ul><li>  this.addMatchers({ </li></ul><ul><li>    toBeZeroWhenSubtracting: function(number) { </li></ul><ul><li>      return (this.actual - number) === 0 </li></ul><ul><li>    } </li></ul><ul><li>  }) </li></ul><ul><li>}); </li></ul>
  17. 19. Custom Matchers <ul><li>describe('Custom Matchers', function () { </li></ul><ul><li>  it('should be greater than 0', function () { </li></ul><ul><li>    expect(1).toBeGreaterThanZero(); </li></ul><ul><li>  }); </li></ul><ul><li>  it('should equal zero when subtracting two numbers', function() { </li></ul><ul><li>    expect(5).toBeZeroWhenSubtracting(5); </li></ul><ul><li>  }); </li></ul><ul><li>}); </li></ul>
  18. 20. RSpec vs. Jasmine: Stubbing # RSpec  it &quot;should add the numbers&quot; do       calc = Calculator.new       calc.stub!(:add).and_return(3)       calc.add(1,1).should == 3 end  // Jasmine  it(&quot;should add the numbers&quot;, function() {       var calc = new Calculator();       spyOn(calc, 'add').andReturn(3);      expect(calc.Add(1,1)).toEqual(3);  });
  19. 21. TDD? &quot; Red , Green , Refactor&quot;
  20. 22. Why do *I* like TDD?
  21. 23. Jasmine with &quot;vanilla&quot; JavaScript <ul><li>- Download &quot;Stand alone&quot;  </li></ul><ul><li>  </li></ul><ul><li>http://pivotal.github.com/jasmine/download.html </li></ul>
  22. 28. describe(&quot;Calculator&quot;, function() {    }); Spec for Calculator:
  23. 29. describe(&quot;Calculator&quot;, function() {   var calc;   beforeEach(function(){     calc = new Calculator();   }); }); Spec for Calculator:
  24. 30. describe(&quot;Calculator&quot;, function() {   var calc;   beforeEach(function(){     calc = new Calculator();   }); }); Spec for Calculator:
  25. 31. describe(&quot;Calculator&quot;, function() {   var calc;   beforeEach(function(){     calc = new Calculator();   });   it(&quot;should return the sum&quot;, function() {     expect(calc.Add(1,1)).toEqual(2);   }); }); Spec for Calculator:
  26. 32. Failing Test
  27. 33. Create the &quot;Calculator&quot; function <ul><li>function Calculator () { </li></ul><ul><li>} </li></ul>
  28. 34. One passing, one left to fix
  29. 35. Add the method <ul><li>function Calculator () {   this.Add = function(num1, num2){     return num1 + num2;   }; } </li></ul>
  30. 36. Passed!
  31. 37. Jasmine with Ruby(not Rails)
  32. 38. $ gem install jasmine
  33. 39. $ jasmine init
  34. 40. Generated folder structure
  35. 41. $ rake jasmine
  36. 42. http://localhost:8888
  37. 43. $ rake jasmine:ci
  38. 44. Jasmine with JQuery
  39. 45.      * toBe(jQuerySelector)     * toBeChecked()     * toBeEmpty()     * toBeHidden()     * toBeSelected()     * toBeVisible()     * toContain(jQuerySelector)     * toExist()     * toHaveAttr(attributeName, attributeValue)     * toHaveBeenTriggeredOn(selector)     * toHaveClass(className)     * toHaveData(key, value)     * toHaveHtml(string)     * toHaveId(id)     * toHaveText(string)     * toHaveValue(value)     * toBeDisabled() jasmine-jquery Matchers
  40. 46. &quot;A lightweight, easy to use Javascript <span> injector for radical Web Typography&quot;
  41. 47. @davatron5000
  42. 48. Lettering.js <h1 class=&quot;fancy_title&quot;>Some Title</h1> <script>   $(document).ready(function() {     $(&quot;.fancy_title&quot;).lettering();   }); </script>
  43. 49. Lettering.js results <ul><li><h1 class=&quot;fancy_title&quot;> </li></ul><ul><li>  <span class=&quot;char1&quot;>S</span> </li></ul><ul><li>  <span class=&quot;char2&quot;>o</span> </li></ul><ul><li>  <span class=&quot;char3&quot;>m</span> </li></ul><ul><li>  <span class=&quot;char4&quot;>e</span> </li></ul><ul><li>  <span class=&quot;char5&quot;></span> </li></ul><ul><li>  <span class=&quot;char6&quot;>T</span> </li></ul><ul><li>  <span class=&quot;char7&quot;>i</span> </li></ul><ul><li>  <span class=&quot;char8&quot;>t</span> </li></ul><ul><li>  <span class=&quot;char9&quot;>l</span> </li></ul><ul><li>  <span class=&quot;char10&quot;>e</span> </li></ul><ul><li></h1> </li></ul>
  44. 50. Standalone folder structure + more
  45. 51. <ul><li><!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; </li></ul><ul><li>  &quot;http://www.w3.org/TR/html4/loose.dtd&quot;> </li></ul><ul><li><html> </li></ul><ul><li><head> </li></ul><ul><li>  <title>Jasmine Test Runner</title> </li></ul><ul><li>  <link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;lib/jasmine-1.0.2/jasmine.css&quot;> </li></ul><ul><li>  <script type=&quot;text/javascript&quot; src=&quot;lib/jasmine-1.0.2/jasmine.js&quot;></script> </li></ul><ul><li>  <script type=&quot;text/javascript&quot; src=&quot;lib/jasmine-1.0.2/jasmine-html.js&quot;></script> </li></ul><ul><li>  <script type=&quot;text/javascript&quot; src=&quot;lib/jquery-1.6.1.min.js&quot;></script> </li></ul><ul><li>  <script type=&quot;text/javascript&quot; src=&quot;lib/jasmine-jquery-1.2.0.js&quot;></script> </li></ul><ul><li>  <script type=&quot;text/javascript&quot; src=&quot;lib/jquery.lettering-0.6.1.min.js&quot;></script> </li></ul><ul><li>  <script type=&quot;text/javascript&quot; src=&quot;spec/LetteringSpec.js&quot;></script> </li></ul><ul><li></head> </li></ul><ul><li><body> </li></ul><ul><li><script type=&quot;text/javascript&quot;> </li></ul><ul><li>  jasmine.getEnv().addReporter(new jasmine.TrivialReporter()); </li></ul><ul><li>  jasmine.getEnv().execute(); </li></ul><ul><li></script> </li></ul><ul><li></body> </li></ul><ul><li></html> </li></ul>
  46. 52. <ul><li>describe(&quot;Lettering&quot;, function(){ </li></ul><ul><li>  beforeEach(function(){ </li></ul><ul><li>    //loadFixtures('myfixture.html'); </li></ul><ul><li>    setFixtures('<h1 class=&quot;fancy_title&quot;>Some Title</h1>'); </li></ul><ul><li>    $('.fancy_title').lettering(); </li></ul><ul><li>  }); </li></ul><ul><li>}); </li></ul>
  47. 53. <ul><li>describe(&quot;Lettering&quot;, function(){ </li></ul><ul><li>  beforeEach(function(){ </li></ul><ul><li>    //loadFixtures('myfixture.html'); </li></ul><ul><li>    setFixtures('<h1 class=&quot;fancy_title&quot;>Some Title</h1>'); </li></ul><ul><li>    $('.fancy_title').lettering(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should be visible&quot;, function() { </li></ul><ul><li>    expect($('.fancy_title')).toBeVisible(); </li></ul><ul><li>  }); </li></ul><ul><li>}); </li></ul>
  48. 54. <ul><li>describe(&quot;Lettering&quot;, function(){ </li></ul><ul><li>  beforeEach(function(){ </li></ul><ul><li>    //loadFixtures('myfixture.html'); </li></ul><ul><li>    setFixtures('<h1 class=&quot;fancy_title&quot;>Some Title</h1>'); </li></ul><ul><li>    $('.fancy_title').lettering(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should be visible&quot;, function() { </li></ul><ul><li>    expect($('.fancy_title')).toBeVisible(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should have 10 spans&quot;, function(){ </li></ul><ul><li>    expect($('.fancy_title > span').length).toEqual(10); </li></ul><ul><li>  }); </li></ul><ul><li>}); </li></ul>
  49. 55. <ul><li>describe(&quot;Lettering&quot;, function(){ </li></ul><ul><li>  beforeEach(function(){ </li></ul><ul><li>    //loadFixtures('myfixture.html'); </li></ul><ul><li>    setFixtures('<h1 class=&quot;fancy_title&quot;>Some Title</h1>'); </li></ul><ul><li>    $('.fancy_title').lettering(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should be visible&quot;, function() { </li></ul><ul><li>    expect($('.fancy_title')).toBeVisible(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should have 10 spans&quot;, function(){ </li></ul><ul><li>    expect($('.fancy_title > span').length).toEqual(10); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should contain 'S' as the text of the first span&quot;, function(){ </li></ul><ul><li>    expect($('.fancy_title > span:first').text()).toEqual('S'); </li></ul><ul><li>  }); </li></ul><ul><li>}); </li></ul>
  50. 56. <ul><li>describe(&quot;Lettering&quot;, function(){ </li></ul><ul><li>  beforeEach(function(){ </li></ul><ul><li>    //loadFixtures('myfixture.html'); </li></ul><ul><li>    setFixtures('<h1 class=&quot;fancy_title&quot;>Some Title</h1>'); </li></ul><ul><li>    $('.fancy_title').lettering(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should be visible&quot;, function() { </li></ul><ul><li>    expect($('.fancy_title')).toBeVisible(); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should have 10 spans&quot;, function(){ </li></ul><ul><li>    expect($('.fancy_title > span').length).toEqual(10); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should contain 'S' as the text of the first span&quot;, function(){ </li></ul><ul><li>    expect($('.fancy_title > span:first').text()).toEqual('S'); </li></ul><ul><li>  }); </li></ul><ul><li>  it(&quot;should have a class of 'char1' on the first span&quot;, function(){ </li></ul><ul><li>    expect($('.fancy_title > span:first')).toHaveClass('char1'); </li></ul><ul><li>  }); </li></ul><ul><li>}); </li></ul>
  51. 57. Jasmine with Rails gem &quot;jasmine&quot;  $ bundle install $ jasmine init (optional) $ rake jasmine or  $ rake jasmine:ci http://localhost:8888
  52. 58. Generated Rails spec folder
  53. 59. Generated default javascript objects
  54. 60. $ rake jasmine 
  55. 62. $ gem install evergreen
  56. 63. gem install evergreen
  57. 64. Evergreen default folder paths  (not generated)
  58. 65. $ evergreen serve
  59. 66. $ evergreen run
  60. 67. Evergreen and Rails 3 <ul><li>gem 'evergreen', :require => evergreen/rails'localhost:3000/evergreen </li></ul><ul><li>rake spec:javascripts </li></ul>
  61. 68. What about CoffeeScript???
  62. 69. Installing CoffeeScript <ul><li>brew install node.js (then add to PATH, NODE_PATH) </li></ul><ul><li>curl http://npmjs.org/install.sh | sh </li></ul><ul><li>npm install -g coffee-script </li></ul>
  63. 70. Add  a &quot;_spec.coffee&quot; file
  64. 71. <ul><li>require('/calculator.js') </li></ul><ul><li>describe 'Calculator', -> </li></ul><ul><li>  beforeEach -> </li></ul><ul><li>    @calc = new Calculator </li></ul><ul><li>  it 'should return the sum', -> </li></ul><ul><li>    expect(@calc.Add(1,1)).toEqual(2) </li></ul>
  65. 72. <ul><li>require('/calculator.js') </li></ul><ul><li>describe 'Calculator', -> </li></ul><ul><li>  beforeEach -> </li></ul><ul><li>    @calc = new Calculator </li></ul><ul><li>  it 'should return the sum', -> </li></ul><ul><li>    expect(@calc.Add(1,1)).toEqual(2) </li></ul>
  66. 73. <ul><li>require('/calculator.js') </li></ul><ul><li>describe 'Calculator', -> </li></ul><ul><li>  beforeEach -> </li></ul><ul><li>    @calc = new Calculator </li></ul><ul><li>  it 'should return the sum', -> </li></ul><ul><li>    expect(@calc.Add(1,1)).toEqual(2) </li></ul>
  67. 74. #winning
  68. 76. Headless Browser Install <ul><li>- Download and install Qt 4.7+ binary package </li></ul><ul><li>- gem install capybara-webkit -v=1.0.0.beta4 </li></ul><ul><li>- create &quot;config/evergreen.rb&quot; </li></ul>
  69. 77. Configure Evergreen <ul><li>require 'capybara-webkit' </li></ul><ul><li>Evergreen.configure do |config| </li></ul><ul><li>  #config.driver = :selenium </li></ul><ul><li>  config.driver = :webkit </li></ul><ul><li>  config.public_dir = 'public' </li></ul><ul><li>  config.spec_dir = 'spec/javascripts' </li></ul><ul><li>end </li></ul>
  70. 78. Using a Headless Browser <ul><li>#selenium </li></ul><ul><li>Finished in 3.92 seconds </li></ul><ul><li>2 examples, 0 failures </li></ul><ul><li>#webkit </li></ul><ul><li>Finished in 1.05 seconds </li></ul><ul><li>2 examples, 0 failures </li></ul>
  71. 79. Node.js + Jasmine <ul><li>&quot;jasmine-node&quot; </li></ul>
  72. 80. Any other cool utilities?
  73. 81. Rosie <ul><li>&quot; Rosie is a factory for building JavaScript objects, mostly useful for setting up test data. It is inspired by  factory_girl . &quot; </li></ul><ul><li>https://github.com/bkeepers/rosie </li></ul>
  74. 82. Summer Breeze <ul><li>&quot; Summer Breeze is a tool for generating fixture DOM output for Jasmine JavaScript tests directly from your Rails Views with a simple DSL for specifying fixtures &quot; </li></ul><ul><li>https://github.com/noelrappin/summer_breeze </li></ul>
  75. 83. jasminerice <ul><li>&quot;Pain free coffeescript testing under Rails 3.1&quot; </li></ul><ul><li>https://github.com/bradphelan/jasminerice </li></ul>
  76. 84. http://try-jasmine.heroku.com
  77. 85. Wrap Up <ul><li>1. Unit testing is important </li></ul><ul><li>2. Javascript can and should be unit tested </li></ul><ul><li>3. Jasmine is easy to setup and use </li></ul>
  78. 87. Thank You! @timtyrrell Questions? Did I miss any cool plugins? http://bit.ly/jasmine-lsrc http://spkr8.com/t/7818
  79. 88. http://pivotal.github.com/jasmine/ https://github.com/jnicklas/evergreen https://github.com/velesin/jasmine-jquery https://github.com/thoughtbot/capybara-webkit http://obtiva.com/blog/112-javascript-specs-with-jasmine-a-primer-for-rubyists-part-1 http://obtiva.com/blog/119 http://daverupert.com/2010/09/lettering-js/ http://www.engineyard.com/university/screencasts/javascript-tests-with-jasmine http://blog.levid.com/?p=29 http://blog.carbonfive.com/2010/10/21/rspec-best-practices/ https://github.com/johnbintz/guard-jasmine-headless-webkit References:

    Soyez le premier à commenter

    Identifiez-vous pour voir les commentaires

  • aaronmcadam

    Oct. 31, 2011
  • xzkcz

    Apr. 22, 2012
  • yuletide

    May. 25, 2012
  • yankchina

    Jul. 2, 2012
  • slaboszm

    Oct. 17, 2013
  • cmmtech

    May. 23, 2014
  • junjieli4

    Aug. 18, 2014
  • hanumeshr1

    Nov. 23, 2016

Slides from my Lonestar Ruby Conf 2011 presentation. *** Video of presentation: http://confreaks.com/videos/2531-lsrc2011-testing-javascript-with-jasmine *** Agenda: - Briefly cover why you should unit test - Discuss what Jasmine is and isn't - Show syntax with comparisons to RSpec - Jasmine with: - Vanilla JavaScript - Jasmine with jQuery - Jasmine with Ruby (not Rails) - Jasmine with Rails - Evergreen - capybara-webkit - Where does CoffeeScript, node.js, etc. fit in? - Other helpful libraries/Wrap-up

Vues

Nombre de vues

10 002

Sur Slideshare

0

À partir des intégrations

0

Nombre d'intégrations

414

Actions

Téléchargements

93

Partages

0

Commentaires

0

Mentions J'aime

8

×