Javascript unit testing, yes we can e big

  • 1,986 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,986
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
29
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • Ask everyone to introduce themselves quickly.
  • Who Writes Java? Write Unit tests?
    Who Writes Ruby
    Who Writes JavaScript? Do you write unit tests?
    BDD?
    jQuery?



  • John Resig Survey: http://www.slideshare.net/jeresig/understanding-javascript-testing

    Counter each of these!!!!
  • we wrote something we otherwise would have outsourced to Flash developers-- demo method explorer


  • # nested describes---
    # need button to go to next fieldset
    it("should add 'next' button to first fieldset", function() {
    expect($("form fieldset:first a").text()).to(equal, 'Next');
    });
    it("should add 'next' class to next button", function() {
    expect($("form fieldset:first a").hasClass('next')).to(equal, true);
    });
    it("should add 'next' button to second fieldset", function() {
    expect($("form fieldset:nth(1) a:last").text()).to(equal, 'Next');
    });
    it("should not add 'next' buttons to last fieldset", function() {
    expect($("form fieldset:last a").text()).to(equal, '');
    });

    # code
    $('fieldset:not(:last)').each(function() { $(this).append('<a class="next">Next</a>') });





  • ./script/generate javascript_spec wiz

    # create fixture
    <form action="application.html">
    <fieldset title="A"><input type="text" value="a"/></fieldset>
    <fieldset title="B"><input type="text" value="b"/></fieldset>
    <fieldset title="C"><input type="text" value="c"/></fieldset>
    </form>

    # create simple test
    describe('initialization', function() {
    it("shows the first fieldset", function(){
    expect($("form fieldset:first").is(':visible')).to(equal, true);
    });
    });
    # run from command line

    # tests that fail
    it("hides the second and third fieldset", function(){
    expect($("form fieldset:not(:first)").is(':visible')).to(equal, false);
    });

    # run from command line

    # write code in before block

    var wizardize = function() {
    $('form').each(function() {
    $('fieldset', this).hide();
    $('fieldset:first', this).show();
    });

  • mkdir demo
    cd demo
    rails demo
    cd demo
    ./script/plugin install git://github.com/relevance/blue-ridge.git
    ./script/generate blue_ridge

  • mkdir demo
    cd demo
    rails demo
    cd demo
    ./script/plugin install git://github.com/relevance/blue-ridge.git
    ./script/generate blue_ridge




















Transcript

  • 1. Test-Driven JavaScript with ScrewUnit & BlueRidge Andy Peterson Jonah Williams Carbon Five
  • 2. Introductions
  • 3. Carbon Five Boutique software consulting 20 people, all developers Agile development, collaboration, transparency Mix of projects: start-ups / non-profits / enterprise History of Java, but now RoR + misc.
  • 4. Agenda JavaScript unit testing: how & why BDD, jQuery, plugins Demo TDD with a simple test Problems & lessons learned Q&A
  • 5. Why NOT JS Unit Testing? Can’t get started We don’t; nobody else does Patterns unclear-- what does it look like Too many tools (and arch.) to choose from ... lack of tool & infrastructure support Flakey/bad experiences
  • 6. Why JS Unit Testing? Tests => Confidence => Ambition Take on more challenging requirements More homogenous architecture (w/o Flash) Push logic into browser... scalability Refactor reliably
  • 7. JS Testing Universe Styles of Tests: xUnit: JSUnit, QUnit, YUITest, etc. BDD: JSSpec, ScrewUnit Automation: In-browser w/ Selenium, WebDriver, JSTestDriver Out of browser: Env.js + Rhino
  • 8. Blue Ridge Ruby on Rails plugin (therefore conventions!) Integrates ScrewUnit (BDD) and Smoke (mocking) Glue code and scripts Rhino & Env.js to run out of browser from Larry Karnowski, Runcoderun
  • 9. BDD Language closer to user stories Popularized by RSpec in Ruby describe -- organize before / after blocks Nesting describes -- to DRY One assert should per test example
  • 10. describe Stack do before(:each) do @stack = Stack.new @stack.push :item end describe "#peek" do it "should return the top element" do @stack.peek.should == :item end it "should not remove the top element" do @stack.peek @stack.size.should == 1 end end describe "#pop" do Stack (generated docs) it "should return the top element" do #peek @stack.pop.should == :item - should return the top element end it "should remove the top element" do - should not remove the top @stack.pop element @stack.size.should == 0 #pop end - should return the top element end end - should remove the top element
  • 11. BDD in RSpec describe 'a man' { before { @man = Man.new :luck=>5 } describe '#decrement_luck' { it "decrements the luck field by the given amount" { @man.decrement_luck(3) @man.luck.should == 2 } } ... });
  • 12. BDD in ScrewUnit describe('Man', function() { var man; before(function() { man = new Man({luck: 5}); }); describe('#decrement_luck', function() { it("decrements the luck field by the given amount", function() { man.decrement_luck(3); expect(man.luck()).to(equal, 2) }); }); ... });
  • 13. Let’s See It
  • 14. Wizard-izer (our example) Given a form comprised of fieldsets Creates a “panel” for each fieldset Hides all but the first panel Adds buttons to navigate panels etc.
  • 15. Blue Ridge Installation http://github.com/relevance/blue-ridge/tree/master # Within a rails project > ./script/plugin install git:// github.com/relevance/blueridge.git > ./script/generate blue_ridge > ./script/generate javascript_spec wiz
  • 16. Maven Installation http://code.google.com/p/javascript-test-maven-plugin/ <plugin> <executions><execution> <goals> <goal>javascript-test</goal> </goals> </execution></executions> <groupId>com.carbonfive.javascript-test</groupId> <artifactId>javascript-test-maven-plugin</artifactId> <version>1.0-beta1</version> <configuration> <includes> <include>src/test/javascript/suite*.html</include> </includes> </configuration> </plugin>
  • 17. 3 Components Fixture - markup that JS requires test/javascript/widget.html Spec - tests test/javascript/specs/widget_spec.js) Code to test - independent JS <public>/javascript/widget.js
  • 18. jQuery Functional DOM manipulation One function $: $(selector) eg. $(‘p.cls’) Chainable -- $ (‘p.cls’).addClass(‘abc’).removeClass(‘cls’).etc(...) Plugins
  • 19. jQuery Plugin Add function to jQuery.fn.reverse() = function() { jQuery object // “this” is list of nodes Receive list of nodes $(this).each(function() { var t = $(this).text(); Do your stuff $(this).text(t); } Return “this” return this; Good tutorials online }
  • 20. DOM cleanup Tools don’t reset your DOM automatically They are writing status back to the page (yuck!) Solution Wrap fixtures (in #fixture container) before function that restores DOM state
  • 21. DOM cleanup fn // before(function() { $('#fixture).fixture(); }); jQuery.fn.fixture = function() { this.each(function() { if (this.original) { $(this).html(this.original); } else { this.original = $(this).html(); } }); }
  • 22. Put CSS in Fixture Helps with debugging Use FireBug to inspect
  • 23. Structure as a jQuery plugin jQuery is not required-- but really helps you organize code Separate document.ready() from code-- dependency injection Use as organizing principal, and dependency injection Write modular code, instead page-specific code
  • 24. Learnings
  • 25. Not Hard to Make JS Testing a Part of Your Process
  • 26. Markup Design Generated in JS? On the server? Hybrid? Unit testing encourages generating more markup in JavaScript Will affect SEO and accessibility (good or bad)
  • 27. When to test Some JS can be experimental Test-drive when you have a good sense of what he component is Testing is a refactoring tool As code gets complicated, pull into testable units
  • 28. Don’t Be Afraid of JS Reminder wizard Method chooser demo-- data driven JS, with ajax structure
  • 29. What to Unit Test / Limitations AJAX JavaScript Unit Testing setTimeout() setInterval() DOM Business Manipulation Logic Animations Computed sizes
  • 30. It’s Not Browser Testing ...it’s JS unit testing Not cross-browser testing Not your production markup Functional test framework still have a place
  • 31. Our Testing Stack Selenium Integration & Browser Testing 1/10th Controller/View Integration Tests 1/5th Javascript Unit Testing Model Unit Controller Unit 1/10th Tests Tests
  • 32. JavaScript Testing Yes We Can! Andy Peterson Jonah Williams andy@carbonfive.com jonah@carbonfive.com skype: ndpsoft
  • 33. Blue Ridge TODOs Run in more browsers (not just Firefox) Speed Events Driving in multiple browsers Using code served from app Shenandoah
  • 34. Other Options ScrewUnit Server Selenium + JSUnit testswarm (?)
  • 35. References (Bibliography) http://github.com/relevance/blue-ridge http://pivotallabs.com/users/nick/blog/articles/455- better-javascript-testing-through-screwunit http://github.com/ndp/wizardize http://www.slideshare.net/jeresig/understanding- javascript-testing http://code.google.com/p/javascript-test-maven- plugin/