Slide 1

Slide 1 text

http://github.com/sathomas/jsunittest [email protected] 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

Slide 2

Slide 2 text

Finding Bugs is a Bitch!

Slide 3

Slide 3 text

What If We Could “Childproof” Our Code?

Slide 4

Slide 4 text

Continuous Test Driven Development Block bugs from getting into our code at all.

Slide 5

Slide 5 text

1. Frictionless testing during development 2. Re-use of tests for integration 3. Coverage reports


Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Example Application

Slide 8

Slide 8 text

1. Test Development Environment

Slide 9

Slide 9 text

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" ] }

Slide 10

Slide 10 text

Test Driven Development 1. Write a Test 2. Verify That It Fails 3. Make It Pass 4. Repeat As Necessary

Slide 11

Slide 11 text

First Test describe("Application", function(){ it("creates global variable…", function(){ should.exist(todoApp); }) })

Slide 12

Slide 12 text

Passing Code if (typeof todoApp === "undefined") { todoApp = {}; }

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

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(""); }) }) …

Slide 17

Slide 17 text

Make The Tests Pass todoApp.Todo = Backbone.Model.extend({ defaults: { title: "", complete: false } })

Slide 18

Slide 18 text

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"); })

Slide 19

Slide 19 text

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"); })

Slide 20

Slide 20 text

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(); }) })

Slide 21

Slide 21 text

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; })

Slide 22

Slide 22 text

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; })

Slide 23

Slide 23 text

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; })

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

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; })

Slide 26

Slide 26 text

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; })

Slide 27

Slide 27 text

2. Command-Line Test Execution

Slide 28

Slide 28 text

Test Code Setup if (typeof exports !== 'undefined' &&
 this.exports !== exports) { var jsdom = require("jsdom").jsdom; var doc=jsdom(""); var window = doc.createWindow(); var $ = require("jquery")(window); global._ = require("underscore"); global.Backbone = require("backbone"); Backbone.$ = $; var chai = require("chai"); var sinon = require("sinon"); }

Slide 29

Slide 29 text

Mocha Options:
 mocha.opts test/app-todos-test.js src/app-todos.js

Slide 30

Slide 30 text

Run Mocha

Slide 31

Slide 31 text

3. Test Coverage

Slide 32

Slide 32 text

Install Blanket.js

Slide 33

Slide 33 text

Generate Coverage Report

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

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