Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Unit Testing JavaScript Applications
Stephen Thomas
February 09, 2014
Technology
5
2.3k
Unit Testing JavaScript Applications
Video of presentation at
http://www.infoq.com/presentations/tdd-javascript
Stephen Thomas
February 09, 2014
Tweet
Share
More Decks by Stephen Thomas
See All by Stephen Thomas
sathomas
0
19
sathomas
0
79
sathomas
0
2.1k
sathomas
1
2.3k
sathomas
0
2.1k
sathomas
4
360
sathomas
8
640
sathomas
2
280
Other Decks in Technology
See All in Technology
mochan_tk
1
110
nkjzm
0
550
miyake
1
390
subroh0508
4
220
clustervr
0
130
ihcomega56
1
440
clustervr
0
130
kaedemalu
0
310
conciergeu
0
120
myajiri
0
300
raykataoka
9
7.8k
whitefox_73
0
180
Featured
See All Featured
rmw
11
810
eitanlees
112
10k
smashingmag
283
47k
3n
163
22k
malarkey
393
61k
dotmariusz
94
5.5k
ddemaree
273
31k
danielanewman
1
510
malarkey
192
8.6k
lynnandtonic
272
16k
lara
15
2.7k
productmarketing
5
710
Transcript
http://github.com/sathomas/jsunittest stephen@sathomas.me icon-comment-alt icon-comments icon-comments-alt icon-credit-card icon-dashboard icon-download icon-download-alt icon-edit
icon-envelope icon-envelope-alt icon-leaf icon-legal icon-lemon icon-lock icon-unlock icon-magic icon-magnet icon-map-marker icon-minus icon-minus-sign icon-resize-vertica icon-retweet icon-road icon-rss icon-screenshot icon-search icon-share icon-share-alt icon-shopping-car http://speakerdeck.com/sathomas Directional Icons icon-arrow-down icon-arrow-left icon-arrow-right icon-arrow-up icon-chevron-down icon-circle-arrow-down icon-circle-arrow-left icon-circle-arrow-right icon-circle-arrow-up icon-chevron-left icon-car icon-car icon-car icon-car icon-ch Video Player Icons icon-play-circle icon-play icon-step-backward icon-fast-backward icon-fas icon-ste Unit Testing JavaScript Applications Stephen Thomas
Finding Bugs is a Bitch!
What If We Could “Childproof” Our Code?
Continuous Test Driven Development Block bugs from getting into our
code at all.
1. Frictionless testing during development 2. Re-use of tests for
integration 3. Coverage reports
1. Frictionless testing during development 2. Re-use of tests for
integration 3. Coverage reports Test’Em: Test Development Environment Mocha+: Command line execution Blanket.js: Coverage analysis
Example Application
1. Test Development Environment
Test’Em Configuration { "framework": "mocha", "src_files": [ "node_modules/jquery/dist/jquery.js", "node_modules/underscore/underscore.js", "node_modules/backbone/backbone.js",
"node_modules/chai/chai.js", "node_modules/sinon/pkg/sinon.js", "src/*.js", "test/*.js" ] }
Test Driven Development 1. Write a Test 2. Verify That
It Fails 3. Make It Pass 4. Repeat As Necessary
First Test describe("Application", function(){ it("creates global variable…", function(){ should.exist(todoApp); })
})
Passing Code if (typeof todoApp === "undefined") { todoApp =
{}; }
None
None
None
Testing a Model describe("Todo Model", function(){ describe("Initialization", function(){ beforeEach(function(){ this.todo
= new todoApp.Todo(); }) it("should default status…", function(){ this.todo.get('complete').should.be.false; }) it("should default title…", function(){ this.todo.get('title').should.equal(""); }) }) …
Make The Tests Pass todoApp.Todo = Backbone.Model.extend({ defaults: { title:
"", complete: false } })
Testing a View describe("Todo List Item View", function(){ beforeEach(function(){ this.todo
= new todoApp.Todo({ title: "Todo"}); this.item = new todoApp.TodoListItem({ model: this.todo}); }) it("render() should return view", function(){ this.item.render().should.equal(this.item); }); it("should render as list item", function(){ this.item.render() .el.nodeName.should.equal("LI"); })
Stubs describe("Todo Model", function(){ describe("Attributes", function(){ beforeEach(function(){ this.todo = new
todoApp.Todo(); this.stb = sinon.stub(this.todo,"save"); }) afterEach(function(){ this.stb.restore(); }) it(“should set title attr…", function(){ this.todo.set('title',"Test"); this.todo.get('title') .should.equal("Test"); })
Mocking a REST API describe("REST API", function(){ it("should load via
the API", function(){ this.ajax = sinon.stub($,"ajax") .yieldsTo("success", [ {id:1, title:"Mock1", complete:false} ]); this.todos = new todoApp.Todos(); this.todos.fetch(); this.todos.should.have.length(1); this.todos.at(0).get('title') .should.equal("Mock1"); this.ajax.restore(); }) })
Mocha Tip #1: Never “Comment Out” a Test describe("Todo Model",
function(){ describe("Initialization", function(){ beforeEach(function(){ this.todo = new todoApp.Todo(); }) it("should default…", function(){ this.todo.get('complete').should.be.false; })
Mocha Tip #1: Never “Comment Out” a Test describe("Todo Model",
function(){ describe("Initialization", function(){ beforeEach(function(){ this.todo = new todoApp.Todo(); }) it.skip("should default…", function(){ this.todo.get('complete').should.be.false; })
Mocha Tip #1: Never “Comment Out” a Test describe("Todo Model",
function(){ describe("Initialization", function(){ beforeEach(function(){ this.todo = new todoApp.Todo(); }) it.skip("should default…", function(){ this.todo.get('complete').should.be.false; })
None
Mocha Tip #1b: Skip an Entire Test Block describe.skip("Todo Model",
function(){ describe("Initialization", function(){ beforeEach(function(){ this.todo = new todoApp.Todo(); }) it("should default…", function(){ this.todo.get('complete').should.be.false; })
Mocha Tip #2: Focus on a Single Test describe("Todo Model",
function(){ describe("Initialization", function(){ beforeEach(function(){ this.todo = new todoApp.Todo(); }) it.only("should default…", function(){ this.todo.get('complete').should.be.false; })
2. Command-Line Test Execution
Test Code Setup if (typeof exports !== 'undefined' && this.exports
!== exports) { var jsdom = require("jsdom").jsdom; var doc=jsdom("<html><body></body></html>"); var window = doc.createWindow(); var $ = require("jquery")(window); global._ = require("underscore"); global.Backbone = require("backbone"); Backbone.$ = $; var chai = require("chai"); var sinon = require("sinon"); }
Mocha Options: mocha.opts test/app-todos-test.js src/app-todos.js
Run Mocha
3. Test Coverage
Install Blanket.js
Generate Coverage Report
None
None
Resources • Test Development Environment Test’em: https://github.com/airportyh/testem • Command Line
JavaScript Execution Environment node.js: http://nodejs.org • JavaScript Unit Testing Framework Mocha: http://visionmedia.github.io/mocha/ • JavaScript Assertion Library Chai: http://chaijs.com • Spies, Stubs, and Mocks Sinon.JS: http://sinonjs.org • Test Coverage Blanket.js: http://blanketjs.org