Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JavaScript Unit Testing with Jasmine

4,418 views

Published on

Presentation in javascript.lv meetup

Published in: Technology

JavaScript Unit Testing with Jasmine

  1. 1. JavaScriptunit testing with
  2. 2. @rsim github.com/rsimRaimonds Simanovskis
  3. 3. The easiest Business Intelligence tool on the Web
  4. 4. Using threadsin Ruby applications
  5. 5. Using threadsin JavaScript applications
  6. 6. You can’t :)
  7. 7. JavaScriptunit testing with
  8. 8. RSpec-like testing for JavaScript
  9. 9. Syntaxdescribe("A suite", function() { it("contains spec with an expectation", function() { expect(true).toBe(true); });});describe("A suite is just a function", function() { var a; it("and so is a spec", function() { a = true; expect(a).toBe(true); });});
  10. 10. Matchersdescribe("The toBe matcher compares with ===", function() { it("and has a positive case ", function() { expect(true).toBe(true); }); it("and can have a negative case", function() { expect(false).not.toBe(true); });});
  11. 11. Included matchers toBe toContain toEqual toBeLessThan toMatch toBeGreaterThan toBeDefined toBeCloseTo toBeUndefined toThrow toBeNull toBeTruthy toBeFalsy
  12. 12. Setup & teardowndescribe("A spec (with setup and tear-down)", function() { var foo; beforeEach(function() { foo = 0; foo += 1; }); afterEach(function() { foo = 0; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); it("can have more than one expectation", function() { expect(foo).toEqual(1); expect(true).toEqual(true); });});
  13. 13. describe("A spec", function() { var foo; beforeEach(function() { Nesting foo = 0; foo += 1; }); afterEach(function() { foo = 0; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); it("can have more than one expectation", function() { expect(foo).toEqual(1); expect(true).toEqual(true); }); describe("nested inside a second describe", function() { var bar; beforeEach(function() { bar = 1; }); it("can reference both scopes as needed ", function() { expect(foo).toEqual(bar); }); });});
  14. 14. Disablingxdescribe("A spec", function() { var foo; beforeEach(function() { foo = 0; foo += 1; }); xit("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); });});
  15. 15. describe("A spy", function() { Spies var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, setBar); foo.setBar(123); foo.setBar(456, another param); }); it("tracks that the spy was called", function() { expect(foo.setBar).toHaveBeenCalled(); }); it("tracks its number of calls", function() { expect(foo.setBar.calls.length).toEqual(2); }); it("tracks all the arguments of its calls", function() { expect(foo.setBar).toHaveBeenCalledWith(123); expect(foo.setBar).toHaveBeenCalledWith(456, another param); }); it("allows access to the most recent call", function() { expect(foo.setBar.mostRecentCall.args[0]).toEqual(456); }); it("allows access to other calls", function() { expect(foo.setBar.calls[0].args[0]).toEqual(123); }); it("stops all execution on a function", function() { expect(bar).toBeNull(); });});
  16. 16. describe("A spy, when faking a return value", function() { var foo, bar, fetchedBar; beforeEach(function() { andReturn foo = { setBar: function(value) { bar = value; }, getBar: function() { return bar; } }; spyOn(foo, getBar).andReturn(745); foo.setBar(123); fetchedBar = foo.getBar(); }); it("tracks that the spy was called", function() { expect(foo.getBar).toHaveBeenCalled(); }); it("should not effect other functions", function() { expect(bar).toEqual(123); }); it("when called returns the requested value", function() { expect(fetchedBar).toEqual(745); });});
  17. 17. Async testsdescribe("Asynchronous specs", function() { var value, flag; it("should support async execution of test preparation andexepectations", function() { runs(function() { flag = false; value = 0; setTimeout(function() { flag = true; }, 500); }); waitsFor(function() { value++; return flag; }, "The Value should be incremented", 750); runs(function() { expect(value).toBeGreaterThan(0); }); });});
  18. 18. Jasmine tests runner Demo
  19. 19. Works nicewith CoffeeScriptand Backbone.js
  20. 20. Testing Backbone.js modeldescribe "Todo", -> todo = null ajaxCall = (param) -> jQuery.ajax.mostRecentCall.args[0][param] beforeEach -> todo = new TodoApp.Todo todos = new TodoApp.TodoList [todo] it "should initialize with empty content", -> expect(todo.get "content").toEqual "empty todo..." it "should initialize as not done", -> expect(todo.get "done").toBeFalsy() it "should save after toggle", -> spyOn jQuery, "ajax" todo.toggle() expect(ajaxCall "url").toEqual "/todos" expect(todo.get "done").toBeTruthy()
  21. 21. and collectiondescribe "TodoList", -> attributes = [ content: "First" done: true , content: "Second" ] todos = null beforeEach -> todos = new TodoApp.TodoList attributes it "should return done todos", -> expect(_.invoke todos.done(), "toJSON").toEqual [attributes[0]] it "should return remaining todos", -> expect(_.invoke todos.remaining(), "toJSON").toEqual [attributes[1]]
  22. 22. jasmine-jquery• a set of custom matchers for jQuery framework• an API for handling HTML, CSS, and JSON fixtures in your specs
  23. 23. expect($(<div id="some-id"></div>)).toBe(div#some-id)expect($(<input type="checkbox" checked="checked"/>)).toBeChecked()expect($(<div style="display: none; margin: 10px;"></div>)).toHaveCss({display: "none", margin: "10px"})expect($(<option selected="selected"></option>)).toBeSelected()expect($(<div><span class="some-class"></span></div>)).toContain(span.some-class)expect($(<div class="some-class"></div>)).toHaveClass("some-class")expect($(<div><span></span></div>)).toHaveHtml(<span></span>)expect($(<div><ul></ul><h1>header</h1></div>)).toContainHtml(<ul></ul>)expect($(<div>some text</div>)).toHaveText(some text)expect($(<input type="text" value="some text"/>)).toHaveValue(sometext)expect(<input type=submit disabled=disabled/>).toBeDisabled()expect($(<input type=text />).focus()).toBeFocused()
  24. 24. HTML fixturesIn myfixture.html file:<div id="my-fixture">some complex content here</div>Inside your test:loadFixtures(myfixture.html);$(#my-fixture).myTestedPlugin();expect($(#my-fixture)).to...;
  25. 25. jasmine-fixture// Lets say you want to write a Jasmine spec for some code// that needs to select elements from the DOM with jQuery:$(#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"])// In the good ol days of manually crafting your HTML fixtures,// youd have to append some raw HTML to the DOM like this:beforeEach(function(){ $(<div id="toddler"><div class="hidden toy"><input name="toyName"value="cuddle bunny"></div></div>).appendTo(body);});afterEach(function(){ $(#toddler).remove()});// But jasmine-fixtures affix method lets you do this instead:beforeEach(function(){ affix(#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"])});
  26. 26. jasmine-givendescribe("assigning stuff to this", function() { Given(function() { this.number = 24; }); Given(function() { this.number++; }); When(function() { this.number *= 2; }); Then(function() { return this.number === 50; }); // or Then(function() { expect(this.number).toBe(50) });});describe("assigning stuff to variables", function() { var subject; Given(function() { subject = []; }); When(function() { subject.push(foo); }); Then(function() { return subject.length === 1; }); // or Then(function() { expect(subject.length).toBe(1); });});
  27. 27. jasmine-givendescribe "assigning stuff to this", -> Given -> @number = 24 Given -> @number++ When -> @number *= 2 Then -> @number == 50 # or Then -> expect(@number).toBe(50)describe "assigning stuff to variables", -> subject=null Given -> subject = [] When -> subject.push(foo) Then -> subject.length == 1 # or Then -> expect(subject.length).toBe(1)
  28. 28. jasmine-stealthdescribe("multiple stubbings", function() { var someSpy; beforeEach(function() { someSpy = jasmine.createSpy(); someSpy.when("pirate", { booty: ["jewels",jasmine.any(String)]}).thenReturn("argh!"); someSpy.when("panda",1).thenReturn("sad"); }); it("stubs the first accurately", function() { expect(someSpy("pirate",{ booty: ["jewels","coins"]})).toBe("argh!"); }); it("stubs the second too", function() { expect(someSpy("panda",1)).toBe("sad"); }); it("doesnt return anything when a stubbing isnt satisfied",function(){ expect(someSpy("anything else at all")).not.toBeDefined(); });});
  29. 29. References http://pivotal.github.io/jasmine/ http://searls.testdouble.com/posts/2013-03-21- jasmine-tactics-screencast.htmlhttps://github.com/rsim/backbone_coffeescript_demo https://github.com/rsim/rpn_calculator http://vimeo.com/53655205

×