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.5k
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
Sepsis
sathomas
0
26
Leave No One Behind
sathomas
0
83
Introducing D3.js
sathomas
0
2.2k
Building JavaScript Visualizations Part 1
sathomas
1
2.4k
Building JavaScript Visualizations Part 2
sathomas
0
2.2k
Securing JavaScript Web Applications
sathomas
4
370
Web-Based Visualizations with D3.js
sathomas
8
690
Custom Domains with Github Pages
sathomas
2
290
Other Decks in Technology
See All in Technology
5分で完全理解するGoのiota
uji
3
1.5k
jaws-ug-asa-datasync-20220510
hiashisan
0
430
Accelerating ZOZOTOWN Modernization with Istio
yokawasa
0
210
Power BI Report Ops
hanaseleb
0
140
ITエンジニアを取り巻く環境とキャリアパス / A career path for Japanese IT engineers
takatama
0
520
THETA Xの登場はジオ業界を変えるか?
furuhashilab
0
140
完全に理解した incremetal 〜そして、何もわからないへ〜
mashiike
0
200
Babylon.js v5 新機能の紹介
limes2018
0
320
組織でPower Virtual Agentsを導入するために知っておきたいこと
miyakemito
0
1.3k
株式会社オプティム_採用会社紹介資料 / optim-recruit
optim
0
5.1k
動画配信技術について
yaminoma
0
180
mROS 2のススメ
takasehideki
0
280
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
229
9.3k
Infographics Made Easy
chrislema
233
17k
Build your cross-platform service in a week with App Engine
jlugia
219
17k
Ruby is Unlike a Banana
tanoku
91
9.2k
Building Better People: How to give real-time feedback that sticks.
wjessup
343
17k
It's Worth the Effort
3n
172
25k
Web development in the modern age
philhawksworth
197
9.3k
GitHub's CSS Performance
jonrohan
1020
410k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
19
1.4k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
151
12k
KATA
mclloyd
7
8.5k
The Pragmatic Product Professional
lauravandoore
19
2.8k
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