This document discusses JavaScript unit testing with Jasmine. It provides an overview of Jasmine's syntax including describes, contexts, matches, spies and stubs. It also discusses tools that can be used with Jasmine like jasmine-jquery for DOM testing and jasmine-given for behavior-driven development style tests.
Syntax
describe("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.
Matchers
describe("The 'toBe' matchercompares 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);
});
});
Setup & teardown
describe("Aspec (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.
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.
Disabling
xdescribe("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.
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.
describe("A spy, whenfaking 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.
Async tests
describe("Asynchronous specs",function() {
var value, flag;
it("should support async execution of test preparation and
exepectations", 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);
});
});
});
Testing Backbone.js
model
describe "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.
and collection
describe "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.
jasmine-jquery
• a setof custom matchers for jQuery
framework
• an API for handling HTML, CSS, and
JSON fixtures in your specs
HTML fixtures
In myfixture.htmlfile:
<div id="my-fixture">some complex content here</div>
Inside your test:
loadFixtures('myfixture.html');
$('#my-fixture').myTestedPlugin();
expect($('#my-fixture')).to...;
25.
jasmine-fixture
// Let's sayyou 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,
// you'd 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-fixture's affix method lets you do this instead:
beforeEach(function(){
affix('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]')
});
jasmine-given
describe "assigning stuffto 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.
jasmine-stealth
describe("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("doesn't return anything when a stubbing isn't satisfied",function(){
expect(someSpy("anything else at all")).not.toBeDefined();
});
});