SlideShare a Scribd company logo
1 of 96
Download to read offline
Mocha First Steps
Installing and running tests
Agenda
• JS Unit Testing	

• A first Mocha test	

• Running tests with Karma	

• IDE integration
Getting Ready To Test
• JS Unit tests (try) make sure our JS code
works well
Project Tree
index.html
 
- src
  - main.js
  - buttons.js
  - player.js
 
- style
  - master.css
  - home.css
 
Project Tree
index.html
test.html
 
- src
  - main.js
  - buttons.js
  - player.js
 
- style
  - master.css
  - home.css
 
- spec
  - test_button.js
  - test_player.js
What Mocha Isn’t
• No UI / CSS testing 	

• No server testing
Testing How
Testing Libraries
• Let’s try to write test program for Array	

• Verify indexOf(...) actually works
Array#indexof
var arr1 = [10, 20, 30, 40];
 
if ( arr1.indexOf(20) === 1 ) {
  console.log('success!');
} else {
  console.log('error');
}
What Went Wrong
• Hard to debug	

• Hard to run automatically
We Need …
We Need …
Testing Libraries
• A testing library tells you how to structure
your testing code	


• We’ll use mocha


http://visionmedia.github.io/mocha/
Hello Mocha
var assert = chai.assert;
var array = [10,20,30,40];
 
describe('Array', function() {
!
  describe('#indexOf()', function() {
!
    it('should return -1 when the value is not present',
function() {      
     
assert.equal(array.indexOf(7), -1);
   
}
);
  });
});
Hello Mocha
• describe() defines a block	

• it() defines functionality
Assertions

•

Uses a separate assertions
library	


•
•

I went with Chai	

http://chaijs.com/
Running Our Test:
Karma
Meet Karma
• A test runner for JS	

• Integrates with many IDEs	

• Integrates with CI servers	

• http://karma-runner.github.io/0.10/
index.html
Karma Architecture
Karma
Server
Karma Getting Started
# run just once to install
npm install karma -g
 
# create a project directory
mkdir myproject
cd myproject
 
# create karma configuration file
karma init
Karma Config
• Just a JavaScript file	

• keys determine how test should run
Karma Config
• files is a list of JS files to include in the test	

• Can use wildcards
Karma Config
• browsers is a list of supported browsers
Running Tests
# start a karma server
karma start
 
# execute tests
karma run
IDE Integration
What We Learned
• Mocha is a JS library that helps us write
unit tests	


• Karma is a JS library that helps us run them
Q &A
Advanced Mocha
How to write awesome tests
Agenda
• Flow control: before, after, beforeEach,
afterEach	


• Writing async tests	

• Fixtures and DOM testing
Let’s Flow
describe('Test 1', function() {
  it('should do X', function() {
    var p1 = new Player('bob');
    var p2 = new Player('John');
    var game = new GameEngine(p1, p2);
 
    // test stuff with game
  });
 
  it('should do Y', function() {
    var p1 = new Player('bob');
    var p2 = new Player('John');
    var game = new GameEngine(p1, p2);
 
    // test stuff with game
  });
});
Let’s Flow
describe('Test 1', function() {
  it('should do X', function() {
    var p1 = new Player('bob');
    var p2 = new Player('John');
    var game = new GameEngine(p1, p2);
 
    // test stuff with game
  });
 
  it('should do Y', function() {
    var p1 = new Player('bob');
    var p2 = new Player('John');
    var game = new GameEngine(p1, p2);
 
    // test stuff with game
  });
});

Same code...
A Better Scheme
•

beforeEach() runs
before each test	


•

also has:	


•
•

afterEach() for
cleanups	


describe('Test 1', function() {!
  var game;!
 !
  beforeEach(function() {!
    var p1 = new Player('bob');!
    var p2 = new Player('John');!
    game = new GameEngine(p1, p2);!
  });!
 !
  it('should do X', function() {!
    // test stuff with game!
  });!

!

before() and
after() run once
in the suite

 !
  it('should do Y', function() {!
    // test stuff with game!
  });!
});
Async Testing
Async Theory
var x = 10
test x

x has the right value	

testing here is OK
Async Theory
$.get(...)
test result

Can’t test now, 	

result not yet ready
Async Theory
• Async calls take callbacks	

• We should tell mocha to wait
Async Code
describe('Test 1', function() {
 
  it('should do wait', function(done) {
    setTimeout(function() {
      // now we can test result
      assert(true);
      done();
    }, 1000);
  });
 
});
Async Code
Taking a function
argument tells
mocha the test will
only end after it’s
called

describe('Test 1', function() {
 
  it('should do wait', function(done) {
    setTimeout(function() {
      // now we can test result
      assert(true);
      done();
    }, 1000);
  });
 
});
Async Code
Calling the callback
ends the test

describe('Test 1', function() {
 
  it('should do wait', function(done) {
    setTimeout(function() {
      // now we can test result
      assert(true);
      done();
    }, 1000);
  });
 
});
Async Notes
• Always call done() or your test will fail on
timeout	


• Default timeout is 2 seconds
Controlling Timeouts
describe('Test 1', function() {
  // set suite specific timeout
  this.timeout(500);
 
  it('should do wait', function(done) {
    // test specific timeout
    this.timeout(2000);    
  });
});
Same goes for Ajax
describe('Test 1', function() {
  // set suite specific timeout
  this.timeout(5000);
 
  it('should get user photo', function(done) {
    $.get('profile.png', function(data) {
      // run tests on data
      done();
    });
  });
});
DOM Testing
Theory
“Real” HTML
body
h1
div

body
img

div

“Test” HTML
Theory
“Real” HTML
body
h1
div

body
img

div

“Test” HTML

img
Theory
images.js
$('img.thumbnail').css({
width: 200,
height: 200
});

fixture.html
<img class="thumbmail" src="home.png" />
Using Fixtures
before(function() {
fixture_el = document.createElement('div');
fixture_el.id = "fixture";
!
document.body.appendChild(fixture_el);
});
!
beforeEach(function() {
fixture_el.innerHTML = window.__html__["fixture.html"];
});
!
Almost Ready
• HTML files are not served by default	

• We need to tell karma to serve it
Serving HTMLs
• Modify files section to include the last
(HTML) pattern

// list of files / patterns to load in the browser
files: [
'lib/**/*.js',
'plugins/**/*.js',
'test/fixtures/*.html',
'spec/*.js'
],
Testing a jQuery Plugin
it('should change the header text lowercase', function() {
$('.truncate').succinct({ size: 100 });
!
var result = $('.truncate').text();
assert.equal( result.length , 100 );
});
Fixtures & DOM
• Define DOM fragments in HTML files	

• Load from test suite	

• Test and clean up
Spying With Sinon
Stubs, Spies and Mock Objects explained
Agenda
• Reasons to mock	

• Vanilla mocking	

• How sinon can help	

• Stubs and Spies	

• Faking timers	

• Faking the server
Reasons To Mock
Reasons To Mock
$.ajax

setTimeout
PersonalData
Reasons To Mock
$.ajax

setTimeout
PersonalData
Reasons To Mock
• PersonalData object can save data to
server	


• If saving failed, it retries 3 times
Reasons To Mock
• Both server and clock are external	

• We prefer to test in isolation
What We Can Do
• Provide our own $.ajax, that won’t go to
the server	


• Provide our own setTimeout that won’t
wait for the time to pass
What We Can Do
• Lab: Given the class here


https://gist.github.com/ynonp/6667146	


• Write a test case to verify sendData
actually retried 3 times
What We Can Do
• Solution:


https://gist.github.com/ynonp/6667284
Mocking Notes
• Solution is far from perfect. 	

• After the test our “fake” methods remain	

• Writing “fake” methods was not trivial
This Calls for Sinon
About Sinon
• A JS mocking library	

• Helps create fake objects	

• Helps tracking them
About Sinon
• Homepage:


http://sinonjs.org/	


• Google Group:


http://groups.google.com/group/sinonjs	


• IRC Channel:


#sinon.js on freenode
Solving with Sinon
• Here’s how sinon might help us with the
previous task	


• Code:


https://gist.github.com/ynonp/6667378
Solution Notes
• Sinon’s fake timer was easier to use than
writing our own	


• Now we have a synchronous test (instead
of async)
Let’s Talk About Sinon
Spies
• A spy is a function that provides the test
code with info about how it was used
Spies Demo
describe('Sinon', function() {
describe('spies', function() {

!
!
!
!
!

it('should keep count', function() {
var s = sinon.spy();
s();
assert.isTrue(s.calledOnce);
s();
assert.isTrue(s.calledTwice);
s();
assert.equal(s.callCount, 3);

});
});
});
Spy On Existing Funcs
describe('Sinon', function() {
describe('spies', function() {
!
it('should keep count', function() {
var p = new PersonalData();
var spy = sinon.spy(p, 'sendData');
!
p.sendData();
!
assert.isTrue( spy.calledOnce );
});
});
});
Spies Notes
• Full API:


http://sinonjs.org/docs/#spies	


• Tip: Use as callbacks
Spy + Action = Stub
Stub Demo
• Let’s fix our starting example	

• We’ll replace $.ajax with a stub	

• That stub always fails
Stub Demo
var stub = sinon.stub(jQuery, 'ajax').yieldsTo('error');
!
describe('Data', function() {
describe('#sendData()', function() {
!
it('should retry 3 times before quitting', function() {
var p = new PersonalData();
p.sendData();
assert.equal(stub.callCount, 1);
});
});
});
What Can Stubs Do
var callback = sinon.stub();
!
callback.withArgs(42).returns(1);
!
callback.withArgs(1).throws("TypeError");
!
Stubs API
• Full Stubs API docs:


http://sinonjs.org/docs/#stubs	


• Main actions:	

• return stuff	

• throw stuff	

• call stuff
Spies Lab
• Given code here:


https://gist.github.com/ynonp/7101081	


• Fill in the blanks to make the tests pass
Fake Timers
• Use sinon.useFakeTimers() to create a
fake timer	


• Use clock.restore() to clear fake timers
Fake Timers
• Use tick(...) to advance	

• Affected methods:	

• setTimeout, setInterval, clearTimeout,
clearInterval	


• Date constructor
Fake Servers
• Testing client/server communication is hard	

• Use fake servers to simplify it
Fake Servers
$.ajax

PersonalData
Fake Servers
Fake

$.ajax

PersonalData
Let’s write a test for the following class
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

function Person(id) {
  var self = this;
 
  self.load = function() {
    var url = '/users/' + id;
 
    $.get('/users/' + id, function(info) {
      self.name = info.name;
      self.favorite_color = info.favorite_color;
    });
  };
}
Testing Plan
• Set-up a fake server	

• Create a new Person	

• call load()	

• verify fields data
Setting Up The Server
1.
2.
3.
4.
5.
6.
7.
8.
9.

var server = sinon.fakeServer.create();
 
var headers  = {"Content-Type" : "application/json"};
var response = JSON.stringify(
                {"name" : "joe", "favorite_color": "blue" });
 
server.respondWith("GET", "/users/7",
                   [200, headers, response]);
// now requesting /user/info.php returns joe's info as a JSON
Loading a Person
1.
2.
3.
4.
5.
6.

var p = new Person(7);
// sends a request
p.load();
 
// now we have 1 pending request, let's fake the response
server.respond();
Verifying the Data
1.
2.
3.
4.
5.
6.

// finally, verify data
expect(p.name).to.eq('joe');
expect(p.favorite_color).to.eq('blue');
 
// and restore AJAX behavior
server.restore();
Fake Server
• Use respondWith() to set up routes	

• Use respond() to send the response
Fake Server
• Regexps are also supported, so this works:
1.
2.
3.
4.
5.
6.

server.respondWith(//todo-items/(d+)/, function (xhr, id) {
    xhr.respond(
      200,
      { "Content-Type": "application/json" },
      '[{ "id": ' + id + ' }]');
});
Fake Server
• For fine grained control, consider fake
XMLHttpRequest 	


• http://sinonjs.org/docs/#server
Wrapping Up
Wrapping Up
• Unit tests work best in isolation	

• Sinon will help you isolate units, by faking
their dependencies
Wrapping Up
• Write many tests	

• Each test verifies a small chunk of code	

• Don’t test everything
Online Resources

• Chai:


http://chaijs.com/	


• Mocha:


http://visionmedia.github.io/mocha/	


• Sinon:


http://sinonjs.org/	


• Karma (test runner):


http://karma-runner.github.io/0.10/index.html
Thanks For Listening
• Ynon Perek	

• http://ynonperek.com	

• ynon@ynonperek.com

More Related Content

What's hot

Jasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishyJasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishyIgor Napierala
 
Good karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaGood karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaExoLeaders.com
 
Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)Deutsche Post
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsFITC
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit TestingAdvanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit TestingLars Thorup
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introductionNir Kaufman
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Roy Yu
 
Painless JavaScript Testing with Jest
Painless JavaScript Testing with JestPainless JavaScript Testing with Jest
Painless JavaScript Testing with JestMichał Pierzchała
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineGil Fink
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaChristopher Bartling
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma Christopher Bartling
 
Unit tests in node.js
Unit tests in node.jsUnit tests in node.js
Unit tests in node.jsRotem Tamir
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSJim Lynch
 
Unit testing in JavaScript with Jasmine and Karma
Unit testing in JavaScript with Jasmine and KarmaUnit testing in JavaScript with Jasmine and Karma
Unit testing in JavaScript with Jasmine and KarmaAndrey Kolodnitsky
 
Testing JavaScript Applications
Testing JavaScript ApplicationsTesting JavaScript Applications
Testing JavaScript ApplicationsThe Rolling Scopes
 
Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express MiddlewareMorris Singer
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSKnoldus Inc.
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Fwdays
 

What's hot (20)

Jasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishyJasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishy
 
Good karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaGood karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with Karma
 
Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit TestingAdvanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 
Angular testing
Angular testingAngular testing
Angular testing
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
 
Painless JavaScript Testing with Jest
Painless JavaScript Testing with JestPainless JavaScript Testing with Jest
Painless JavaScript Testing with Jest
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmine
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and Karma
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
 
Unit tests in node.js
Unit tests in node.jsUnit tests in node.js
Unit tests in node.js
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
Unit testing in JavaScript with Jasmine and Karma
Unit testing in JavaScript with Jasmine and KarmaUnit testing in JavaScript with Jasmine and Karma
Unit testing in JavaScript with Jasmine and Karma
 
Testing JavaScript Applications
Testing JavaScript ApplicationsTesting JavaScript Applications
Testing JavaScript Applications
 
Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express Middleware
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"
 

Similar to Unit Testing JavaScript Applications

Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testingMats Bryntse
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchMats Bryntse
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineGil Fink
 
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRWJest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRWHolger Grosse-Plankermann
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Howsatesgoral
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETBen Hall
 
UI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected JourneyUI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected JourneyOren Farhi
 
SwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup GroupSwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup GroupErnest Jumbe
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
 
Awesomeness of JavaScript…almost
Awesomeness of JavaScript…almostAwesomeness of JavaScript…almost
Awesomeness of JavaScript…almostQuinton Sheppard
 
In search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingIn search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingAnna Khabibullina
 
Describe's Full of It's
Describe's Full of It'sDescribe's Full of It's
Describe's Full of It'sJim Lynch
 
Node.js Development Workflow Automation with Grunt.js
Node.js Development Workflow Automation with Grunt.jsNode.js Development Workflow Automation with Grunt.js
Node.js Development Workflow Automation with Grunt.jskiyanwang
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockRobot Media
 
CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!Ortus Solutions, Corp
 

Similar to Unit Testing JavaScript Applications (20)

Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testing
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
 
Performance patterns
Performance patternsPerformance patterns
Performance patterns
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmine
 
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRWJest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRW
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NET
 
UI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected JourneyUI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected Journey
 
SwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup GroupSwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup Group
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Awesomeness of JavaScript…almost
Awesomeness of JavaScript…almostAwesomeness of JavaScript…almost
Awesomeness of JavaScript…almost
 
In search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingIn search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testing
 
NodeJS
NodeJSNodeJS
NodeJS
 
Describe's Full of It's
Describe's Full of It'sDescribe's Full of It's
Describe's Full of It's
 
Node.js Development Workflow Automation with Grunt.js
Node.js Development Workflow Automation with Grunt.jsNode.js Development Workflow Automation with Grunt.js
Node.js Development Workflow Automation with Grunt.js
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
 
Java Performance Tuning
Java Performance TuningJava Performance Tuning
Java Performance Tuning
 
CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!
 

More from Ynon Perek

09 performance
09 performance09 performance
09 performanceYnon Perek
 
Mobile Web Intro
Mobile Web IntroMobile Web Intro
Mobile Web IntroYnon Perek
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threadsYnon Perek
 
Mobile Devices
Mobile DevicesMobile Devices
Mobile DevicesYnon Perek
 
Architecture app
Architecture appArchitecture app
Architecture appYnon Perek
 
How to write easy-to-test JavaScript
How to write easy-to-test JavaScriptHow to write easy-to-test JavaScript
How to write easy-to-test JavaScriptYnon Perek
 
Introduction to Selenium and Ruby
Introduction to Selenium and RubyIntroduction to Selenium and Ruby
Introduction to Selenium and RubyYnon Perek
 
Introduction To Web Application Testing
Introduction To Web Application TestingIntroduction To Web Application Testing
Introduction To Web Application TestingYnon Perek
 
Qt Design Patterns
Qt Design PatternsQt Design Patterns
Qt Design PatternsYnon Perek
 
Web Application Security
Web Application SecurityWeb Application Security
Web Application SecurityYnon Perek
 
JavaScript DOM Manipulations
JavaScript DOM ManipulationsJavaScript DOM Manipulations
JavaScript DOM ManipulationsYnon Perek
 

More from Ynon Perek (20)

Regexp
RegexpRegexp
Regexp
 
Html5 intro
Html5 introHtml5 intro
Html5 intro
 
09 performance
09 performance09 performance
09 performance
 
Mobile Web Intro
Mobile Web IntroMobile Web Intro
Mobile Web Intro
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threads
 
Vimperl
VimperlVimperl
Vimperl
 
Syllabus
SyllabusSyllabus
Syllabus
 
Mobile Devices
Mobile DevicesMobile Devices
Mobile Devices
 
Network
NetworkNetwork
Network
 
Architecture app
Architecture appArchitecture app
Architecture app
 
Cryptography
CryptographyCryptography
Cryptography
 
How to write easy-to-test JavaScript
How to write easy-to-test JavaScriptHow to write easy-to-test JavaScript
How to write easy-to-test JavaScript
 
Introduction to Selenium and Ruby
Introduction to Selenium and RubyIntroduction to Selenium and Ruby
Introduction to Selenium and Ruby
 
Introduction To Web Application Testing
Introduction To Web Application TestingIntroduction To Web Application Testing
Introduction To Web Application Testing
 
Accessibility
AccessibilityAccessibility
Accessibility
 
Angularjs
AngularjsAngularjs
Angularjs
 
Js memory
Js memoryJs memory
Js memory
 
Qt Design Patterns
Qt Design PatternsQt Design Patterns
Qt Design Patterns
 
Web Application Security
Web Application SecurityWeb Application Security
Web Application Security
 
JavaScript DOM Manipulations
JavaScript DOM ManipulationsJavaScript DOM Manipulations
JavaScript DOM Manipulations
 

Recently uploaded

From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 

Recently uploaded (20)

From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 

Unit Testing JavaScript Applications

  • 1. Mocha First Steps Installing and running tests
  • 2. Agenda • JS Unit Testing • A first Mocha test • Running tests with Karma • IDE integration
  • 3. Getting Ready To Test • JS Unit tests (try) make sure our JS code works well
  • 4. Project Tree index.html   - src   - main.js   - buttons.js   - player.js   - style   - master.css   - home.css  
  • 5. Project Tree index.html test.html   - src   - main.js   - buttons.js   - player.js   - style   - master.css   - home.css   - spec   - test_button.js   - test_player.js
  • 6. What Mocha Isn’t • No UI / CSS testing • No server testing
  • 8. Testing Libraries • Let’s try to write test program for Array • Verify indexOf(...) actually works
  • 9. Array#indexof var arr1 = [10, 20, 30, 40];   if ( arr1.indexOf(20) === 1 ) {   console.log('success!'); } else {   console.log('error'); }
  • 10. What Went Wrong • Hard to debug • Hard to run automatically
  • 13. Testing Libraries • A testing library tells you how to structure your testing code • We’ll use mocha
 http://visionmedia.github.io/mocha/
  • 14. Hello Mocha var assert = chai.assert; var array = [10,20,30,40];   describe('Array', function() { !   describe('#indexOf()', function() { !     it('should return -1 when the value is not present', function() {             assert.equal(array.indexOf(7), -1);     } );   }); });
  • 15. Hello Mocha • describe() defines a block • it() defines functionality
  • 16. Assertions • Uses a separate assertions library • • I went with Chai http://chaijs.com/
  • 18. Meet Karma • A test runner for JS • Integrates with many IDEs • Integrates with CI servers • http://karma-runner.github.io/0.10/ index.html
  • 20. Karma Getting Started # run just once to install npm install karma -g   # create a project directory mkdir myproject cd myproject   # create karma configuration file karma init
  • 21. Karma Config • Just a JavaScript file • keys determine how test should run
  • 22. Karma Config • files is a list of JS files to include in the test • Can use wildcards
  • 23. Karma Config • browsers is a list of supported browsers
  • 24. Running Tests # start a karma server karma start   # execute tests karma run
  • 26. What We Learned • Mocha is a JS library that helps us write unit tests • Karma is a JS library that helps us run them
  • 27. Q &A
  • 28. Advanced Mocha How to write awesome tests
  • 29. Agenda • Flow control: before, after, beforeEach, afterEach • Writing async tests • Fixtures and DOM testing
  • 30. Let’s Flow describe('Test 1', function() {   it('should do X', function() {     var p1 = new Player('bob');     var p2 = new Player('John');     var game = new GameEngine(p1, p2);       // test stuff with game   });     it('should do Y', function() {     var p1 = new Player('bob');     var p2 = new Player('John');     var game = new GameEngine(p1, p2);       // test stuff with game   }); });
  • 31. Let’s Flow describe('Test 1', function() {   it('should do X', function() {     var p1 = new Player('bob');     var p2 = new Player('John');     var game = new GameEngine(p1, p2);       // test stuff with game   });     it('should do Y', function() {     var p1 = new Player('bob');     var p2 = new Player('John');     var game = new GameEngine(p1, p2);       // test stuff with game   }); }); Same code...
  • 32. A Better Scheme • beforeEach() runs before each test • also has: • • afterEach() for cleanups describe('Test 1', function() {!   var game;!  !   beforeEach(function() {!     var p1 = new Player('bob');!     var p2 = new Player('John');!     game = new GameEngine(p1, p2);!   });!  !   it('should do X', function() {!     // test stuff with game!   });! ! before() and after() run once in the suite  !   it('should do Y', function() {!     // test stuff with game!   });! });
  • 34. Async Theory var x = 10 test x x has the right value testing here is OK
  • 35. Async Theory $.get(...) test result Can’t test now, result not yet ready
  • 36. Async Theory • Async calls take callbacks • We should tell mocha to wait
  • 37. Async Code describe('Test 1', function() {     it('should do wait', function(done) {     setTimeout(function() {       // now we can test result       assert(true);       done();     }, 1000);   });   });
  • 38. Async Code Taking a function argument tells mocha the test will only end after it’s called describe('Test 1', function() {     it('should do wait', function(done) {     setTimeout(function() {       // now we can test result       assert(true);       done();     }, 1000);   });   });
  • 39. Async Code Calling the callback ends the test describe('Test 1', function() {     it('should do wait', function(done) {     setTimeout(function() {       // now we can test result       assert(true);       done();     }, 1000);   });   });
  • 40. Async Notes • Always call done() or your test will fail on timeout • Default timeout is 2 seconds
  • 41. Controlling Timeouts describe('Test 1', function() {   // set suite specific timeout   this.timeout(500);     it('should do wait', function(done) {     // test specific timeout     this.timeout(2000);       }); });
  • 42. Same goes for Ajax describe('Test 1', function() {   // set suite specific timeout   this.timeout(5000);     it('should get user photo', function(done) {     $.get('profile.png', function(data) {       // run tests on data       done();     });   }); });
  • 47. Using Fixtures before(function() { fixture_el = document.createElement('div'); fixture_el.id = "fixture"; ! document.body.appendChild(fixture_el); }); ! beforeEach(function() { fixture_el.innerHTML = window.__html__["fixture.html"]; }); !
  • 48. Almost Ready • HTML files are not served by default • We need to tell karma to serve it
  • 49. Serving HTMLs • Modify files section to include the last (HTML) pattern // list of files / patterns to load in the browser files: [ 'lib/**/*.js', 'plugins/**/*.js', 'test/fixtures/*.html', 'spec/*.js' ],
  • 50. Testing a jQuery Plugin it('should change the header text lowercase', function() { $('.truncate').succinct({ size: 100 }); ! var result = $('.truncate').text(); assert.equal( result.length , 100 ); });
  • 51. Fixtures & DOM • Define DOM fragments in HTML files • Load from test suite • Test and clean up
  • 52. Spying With Sinon Stubs, Spies and Mock Objects explained
  • 53. Agenda • Reasons to mock • Vanilla mocking • How sinon can help • Stubs and Spies • Faking timers • Faking the server
  • 57. Reasons To Mock • PersonalData object can save data to server • If saving failed, it retries 3 times
  • 58. Reasons To Mock • Both server and clock are external • We prefer to test in isolation
  • 59. What We Can Do • Provide our own $.ajax, that won’t go to the server • Provide our own setTimeout that won’t wait for the time to pass
  • 60. What We Can Do • Lab: Given the class here
 https://gist.github.com/ynonp/6667146 • Write a test case to verify sendData actually retried 3 times
  • 61. What We Can Do • Solution:
 https://gist.github.com/ynonp/6667284
  • 62. Mocking Notes • Solution is far from perfect. • After the test our “fake” methods remain • Writing “fake” methods was not trivial
  • 63. This Calls for Sinon
  • 64. About Sinon • A JS mocking library • Helps create fake objects • Helps tracking them
  • 65. About Sinon • Homepage:
 http://sinonjs.org/ • Google Group:
 http://groups.google.com/group/sinonjs • IRC Channel:
 #sinon.js on freenode
  • 66. Solving with Sinon • Here’s how sinon might help us with the previous task • Code:
 https://gist.github.com/ynonp/6667378
  • 67. Solution Notes • Sinon’s fake timer was easier to use than writing our own • Now we have a synchronous test (instead of async)
  • 69. Spies • A spy is a function that provides the test code with info about how it was used
  • 70. Spies Demo describe('Sinon', function() { describe('spies', function() { ! ! ! ! ! it('should keep count', function() { var s = sinon.spy(); s(); assert.isTrue(s.calledOnce); s(); assert.isTrue(s.calledTwice); s(); assert.equal(s.callCount, 3); }); }); });
  • 71. Spy On Existing Funcs describe('Sinon', function() { describe('spies', function() { ! it('should keep count', function() { var p = new PersonalData(); var spy = sinon.spy(p, 'sendData'); ! p.sendData(); ! assert.isTrue( spy.calledOnce ); }); }); });
  • 72. Spies Notes • Full API:
 http://sinonjs.org/docs/#spies • Tip: Use as callbacks
  • 73. Spy + Action = Stub
  • 74. Stub Demo • Let’s fix our starting example • We’ll replace $.ajax with a stub • That stub always fails
  • 75. Stub Demo var stub = sinon.stub(jQuery, 'ajax').yieldsTo('error'); ! describe('Data', function() { describe('#sendData()', function() { ! it('should retry 3 times before quitting', function() { var p = new PersonalData(); p.sendData(); assert.equal(stub.callCount, 1); }); }); });
  • 76. What Can Stubs Do var callback = sinon.stub(); ! callback.withArgs(42).returns(1); ! callback.withArgs(1).throws("TypeError"); !
  • 77. Stubs API • Full Stubs API docs:
 http://sinonjs.org/docs/#stubs • Main actions: • return stuff • throw stuff • call stuff
  • 78. Spies Lab • Given code here:
 https://gist.github.com/ynonp/7101081 • Fill in the blanks to make the tests pass
  • 79. Fake Timers • Use sinon.useFakeTimers() to create a fake timer • Use clock.restore() to clear fake timers
  • 80. Fake Timers • Use tick(...) to advance • Affected methods: • setTimeout, setInterval, clearTimeout, clearInterval • Date constructor
  • 81. Fake Servers • Testing client/server communication is hard • Use fake servers to simplify it
  • 84. Let’s write a test for the following class 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. function Person(id) {   var self = this;     self.load = function() {     var url = '/users/' + id;       $.get('/users/' + id, function(info) {       self.name = info.name;       self.favorite_color = info.favorite_color;     });   }; }
  • 85. Testing Plan • Set-up a fake server • Create a new Person • call load() • verify fields data
  • 86. Setting Up The Server 1. 2. 3. 4. 5. 6. 7. 8. 9. var server = sinon.fakeServer.create();   var headers  = {"Content-Type" : "application/json"}; var response = JSON.stringify(                 {"name" : "joe", "favorite_color": "blue" });   server.respondWith("GET", "/users/7",                    [200, headers, response]); // now requesting /user/info.php returns joe's info as a JSON
  • 87. Loading a Person 1. 2. 3. 4. 5. 6. var p = new Person(7); // sends a request p.load();   // now we have 1 pending request, let's fake the response server.respond();
  • 88. Verifying the Data 1. 2. 3. 4. 5. 6. // finally, verify data expect(p.name).to.eq('joe'); expect(p.favorite_color).to.eq('blue');   // and restore AJAX behavior server.restore();
  • 89. Fake Server • Use respondWith() to set up routes • Use respond() to send the response
  • 90. Fake Server • Regexps are also supported, so this works: 1. 2. 3. 4. 5. 6. server.respondWith(//todo-items/(d+)/, function (xhr, id) {     xhr.respond(       200,       { "Content-Type": "application/json" },       '[{ "id": ' + id + ' }]'); });
  • 91. Fake Server • For fine grained control, consider fake XMLHttpRequest • http://sinonjs.org/docs/#server
  • 93. Wrapping Up • Unit tests work best in isolation • Sinon will help you isolate units, by faking their dependencies
  • 94. Wrapping Up • Write many tests • Each test verifies a small chunk of code • Don’t test everything
  • 95. Online Resources • Chai:
 http://chaijs.com/ • Mocha:
 http://visionmedia.github.io/mocha/ • Sinon:
 http://sinonjs.org/ • Karma (test runner):
 http://karma-runner.github.io/0.10/index.html
  • 96. Thanks For Listening • Ynon Perek • http://ynonperek.com • ynon@ynonperek.com