Jasmine BDD for Javascript


Published on

Published in: Technology

Jasmine BDD for Javascript

  1. 1. BDD for JavascriptLuis Alfredo Porras Páez
  2. 2. Everyone meet to Jasmine :)
  3. 3. https://github.com/pivotal/jasmine/wikiA BDD Framework for testing JavaScript.- Does not depend on any other JavaScript frameworks.- Does not require a DOM.- It has a clean, obvious syntax- Heavily influenced by, and borrows the best parts of, ScrewUnit,JSSpec, JSpec, and of course RSpec.
  4. 4. https://github.com/pivotal/jasmine/wikiSpecs "What your code should do"
  5. 5. https://github.com/pivotal/jasmine/wikiExpectations "To express what you expect about the behavior of your code" matcher
  6. 6. https://github.com/pivotal/jasmine/wikiSuites "To Describe a component of your code"
  7. 7. https://github.com/pivotal/jasmine/wikiBefore and After beforeEach( ) => Takes a function that is run before each spec
  8. 8. https://github.com/pivotal/jasmine/wikiBefore and After II
  9. 9. https://github.com/pivotal/jasmine/wikiBefore and After III afterEach( ) => Takes a function that is run after each spec
  10. 10. https://github.com/pivotal/jasmine/wikiBefore and After IV
  11. 11. https://github.com/pivotal/jasmine/wikiBefore and After VSingle-spec After functions
  12. 12. https://github.com/pivotal/jasmine/wikiNested Describes
  13. 13. https://github.com/pivotal/jasmine/wikiDisabling Tests describe => xdescribe it => xit
  14. 14. https://github.com/pivotal/jasmine/wikiMatchers "How you can evaluate your code behavior" 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); expect(x).not.toEqual(y); Every matchers criteria can be inverted by prepending .not
  15. 15. https://github.com/pivotal/jasmine/wikiYour own matcher "We are not slave, we wanna make our own matchers" describe(Hello world, function() { beforeEach(function() { this.addMatchers({ toBeDivisibleByTwo: function() { return (this.actual % 2) === 0; } }); }); it(is divisible by 2, function() { expect(gimmeANumber()).toBeDivisibleByTwo(); }); });
  16. 16. https://github.com/pivotal/jasmine/wikiJasmine becomes SPY GIRL
  17. 17. https://github.com/pivotal/jasmine/wikiSPIES "Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks." Spies should be created in test setup, before expectations. Spies are torn down at the end of every spec. Spies can be checked if they were called or not and what the calling params were. A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall
  18. 18. https://github.com/pivotal/jasmine/wikiSPIES IIspying on an existing function that you dont touch, with spyOn()var Person = function() { };Person.prototype.helloSomeone = function(toGreet) { return this.sayHello() + " " + toGreet; };Person.prototype.sayHello = function() { return "Hello"; };we want to make sure it calls the sayHello() function when we call the helloSomeone() functiondescribe("Person", function() { it("calls the sayHello() function", function() { var fakePerson = new Person(); spyOn(fakePerson, "sayHello");fakePerson.helloSomeone("world"); expect(fakePerson.sayHello).toHaveBeenCalled(); }); });
  19. 19. https://github.com/pivotal/jasmine/wikiSPIES IIIspying on an existing function that you dont touch, with spyOn()var Person = function() { };Person.prototype.helloSomeone = function(toGreet) { return this.sayHello() + " " + toGreet; };Person.prototype.sayHello = function() { return "Hello"; };Now we want to make sure that helloSomeone is called with "world" as its argumentdescribe("Person", function() { it("greets the world", function() { var fakePerson = new Person(); spyOn(fakePerson, "helloSomeone"); fakePerson.helloSomeone("world"); expect(fakePerson.helloSomeone).toHaveBeenCalledWith("world"); }); });
  20. 20. https://github.com/pivotal/jasmine/wikiSPIES IVSpying on an existing function that you modify: use of jasmine.createSpy()var Person = function() { };Person.prototype.helloSomeone = function(toGreet) { return this.sayHello() + " " + toGreet; };Person.prototype.sayHello = function() { return "Hello"; };With Jasmine, you can "empty" the contents of the function while youre testingdescribe("Person", function() { it("says hello", function() { var fakePerson = new Person(); fakePerson.sayHello = jasmine.createSpy("Say-hello spy"); fakePerson.helloSomeone("world"); expect(fakePerson.sayHello).toHaveBeenCalled(); });});
  21. 21. https://github.com/pivotal/jasmine/wikiSPIES V Spying on an existing function that you modify: use of jasmine.createSpy() var Person = function() { }; Person.prototype.helloSomeone = function(toGreet) { return this.sayHello() + " " + toGreet; }; Person.prototype.sayHello = function() { return "Hello"; }; You can specify that a spy function return something fakePerson.sayHello = jasmine.createSpy("Say hello" spy).andReturn("ello ello");You can even give your spy functions something to dofakePerson.sayHello = jasmine.createSpy("Say hello" spy).andCallFake(function() { document.write("Time to say hello!");return "bonjour"; });
  22. 22. https://github.com/pivotal/jasmine/wikiSpying AJAX Spies can be very useful for testing AJAX or other asynchronous behaviors that take callbacks by faking the method firing an async call
  23. 23. https://github.com/pivotal/jasmine/wikiSpy-Specific MatchersWhen working with spies, these matchers are quite handy:expect(x).toHaveBeenCalled()expect(x).toHaveBeenCalledWith(arguments)expect(x).not.toHaveBeenCalled()expect(x).not.toHaveBeenCalledWith(arguments)Spies can be trained to respond in a variety of ways when invoked:spyOn(x, method).andCallThrough() spyOn(x, method).andReturn(arguments)spyOn(x, method).andThrow(exception)spyOn(x, method).andCallFake(function)
  24. 24. https://github.com/pivotal/jasmine/wikiAsynchronous specsThere are three Jasmine functions that hep you with asynchronicity: run(),waitsFor(), and wait(). runs run() blocks execute procedurally, so you dont have to worry about asynchronous code screwing everything up.
  25. 25. https://github.com/pivotal/jasmine/wikiAsynchronous specs IIrunsrun() blocks share functional scope -- this properties will be common to allblocks, but declared vars will not!
  26. 26. https://github.com/pivotal/jasmine/wikiAsynchronous specs IIIwaits(timeout)The function waits( ) works with runs( ) to provide a naive timeout before thenext block is run
  27. 27. https://github.com/pivotal/jasmine/wikiAsynchronous specs IVwaits(timeout)waits( ) allows you to pause the spec for a fixed period of time.But what if you dont know exactly how long you need to wait?waitsFor to the Rescue¡
  28. 28. https://github.com/pivotal/jasmine/wikiAsynchronous specs VwaitsFor(function, optional message, optional timeout)waitsFor() . Provides a better interface for pausing your spec until some otherwork has completed.Jasmine will wait until the provided function returns true before continuingwith the next block. This may mean waiting an arbitrary period of time, or youmay specify a maxiumum period in milliseconds before timing out.describe("Calculator", function() { it("should factor two huge numbers asynchronously", function() { var calc = new Calculator(); var answer = calc.factor(18973547201226, 28460320801839); waitsFor(function() { return calc.answerHasBeenCalculated(); }, "It took too long to find those factors.", 10000);runs(function() { expect(answer).toEqual(9486773600613); }); });});
  29. 29. References Jasmine WikiHow do I Jasmine: Tutorial Jasmine Railcast
  30. 30. You could look at theseJasmine-JQuery: jQuery matchers and fixture loader for JasmineframeworkJasmine Species: Extended BDD grammar and reporting forJasminejasmine-headless-webkit: Uses the QtWebKit widget to run yourspecs without needing to render a pixel.JasmineRice: Utilizing (jasmine) and taking full advantage of theRails 3.1 asset pipeline jasmine rice removes any excuse YOU have fornot testing your out of control sprawl of coffeescript files.
  31. 31. You could look at theseTry Jasmine Online: start with jasmine from your browser :)