SlideShare a Scribd company logo
1 of 57
Download to read offline
Testing Javascript from a
Frontend perspective
Frederic Cabassut - Campanda
The basics of test-driven development
TDD Cycle - Rule #1
You must write a failing test
before you write any production
code.
TDD Cycle - Rule #2
You must not write more of a
test than is sufficient to fail, or
fail to compile.
TDD Cycle - Rule #3
You must not write more
production code than is
sufficient to make the currently
failing test pass.
TDD Cycle
// tests // production code
TDD Cycle
// tests
var expected = "Hello, Fred!";
// production code
TDD Cycle
// tests
var expected = "Hello, Fred!";
// production code
✓
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
Uncaught ReferenceError: getMyObj is not defined
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
function getMyObj() {
}
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
function getMyObj() {
}
Uncaught TypeError: Cannot read property 'greet' of undefined
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
function getMyObj() {
return {};
}
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
function getMyObj() {
return {};
}
Uncaught TypeError: getMyObj(...).greet is not a function
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
function getMyObj() {
return {
greet: function() {
}
};
}
}
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
// production code
function getMyObj() {
return {
greet: function () {
}
};
}
✓
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
assert.equal(expected, actual);
// production code
function getMyObj() {
return {
greet: function() {
}
};
}
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
assert.equal(expected, actual);
// production code
function getMyObj() {
return {
greet: function() {
}
};
}
AssertionError: "Hello, Fred!" == undefined
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
assert.equal(expected, actual);
// production code
function getMyObj() {
return {
greet: function() {
return "Hello, Fred!";
}
};
}
TDD Cycle
// tests
var expected = "Hello, Fred!";
var actual = getMyObj().greet("Fred");
assert.equal(expected, actual);
// production code
function getMyObj() {
return {
greet: function() {
return "Hello, Fred!";
}
};
}
✓
Why Testing ?
- Increase code quality
- Deploy with confidence
- Self-explaining documentation
- Easy to refactor
What do we have to test ?
- User interaction / events
- Manipulating the DOM
- Client-side business logic
- Ajax request (retrieve/send data)
My favorite testing stack:
- Mochajs https://mochajs.org/
- Chaijs http://chaijs.com/
- Sinonjs: http://sinonjs.org/
- My browser (+ livereload)
Let’s create a DatePicker!
Let’s create a DatePicker!
Let’s create a DatePicker!
Let’s create a DatePicker!
Let’s create a DatePicker!
User interaction / events
// tests
it('should initialize a datepicker with
a given element', function() {
var input =
document.createElement('input');
DatePicker.init(input);
});
// production code
window.DatePicker = {
init: function() {}
}
User interaction / events
// tests
it('should initialize a datepicker with
a given element', function() {
var input =
document.createElement('input');
DatePicker.init(input);
});
// production code
window.DatePicker = {
init: function() {}
}
✓
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
});
// production code
window.DatePicker = {
init: function() {}
}
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
var input =
document.createElement('input');
DatePicker.init(input);
});
// production code
window.DatePicker = {
init: function() {}
}
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
var input =
document.createElement('input');
DatePicker.init(input);
});
// production code
window.DatePicker = {
init: function() {}
}
✓
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
});
// production code
window.DatePicker = {
init: function() {}
}
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
});
// production code
window.DatePicker = {
init: function() {}
}
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
});
// production code
window.DatePicker = {
init: function() {}
}
✓
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
var element =
document.getElementById('datePicker');
expect(element).to.be.ok;
});
// production code
window.DatePicker = {
init: function() {}
}
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
var element =
document.getElementById('datePicker');
expect(element).to.be.ok;
});
// production code
window.DatePicker = {
init: function() {}
}
AssertionError: expected null to be truthy
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
var element =
document.getElementById('datePicker');
expect(element).to.be.ok;
});
// production code
window.DatePicker = {
init: function(input) {
[...]
}
}
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
var element =
document.getElementById('datePicker');
expect(element).to.be.ok;
});
// production code
[...]
input.addEventListener('focus',
function() {
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
User interaction / events
// tests
it('should show a datepicker on input
focus', function() {
[...]
var event = new Event('focus');
input.dispatchEvent(event);
var element =
document.getElementById('datePicker');
expect(element).to.be.ok;
});
// production code
[...]
input.addEventListener('focus',
function() {
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
✓
User interaction / events
// tests
it('should stop event propagation',
function() {
});
// production code
[...]
input.addEventListener('focus',
function() {
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
User interaction / events
// tests
it('should stop event propagation',
function() {
[...]
var event = new Event('focus');
var spy = sinon.spy(event,
'stopPropagation');
input.dispatchEvent(event);
expect(spy).to.have.been.calledOnce;
});
// production code
[...]
input.addEventListener('focus',
function() {
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
User interaction / events
// tests
it('should stop event propagation',
function() {
[...]
var event = new Event('focus');
var spy = sinon.spy(event,
'stopPropagation');
input.dispatchEvent(event);
expect(spy).to.have.been.calledOnce;
});
// production code
[...]
input.addEventListener('focus',
function() {
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
expected stopPropagation to have been called exactly once ...
User interaction / events
// tests
it('should stop event propagation',
function() {
[...]
var event = new Event('focus');
var spy = sinon.spy(event,
'stopPropagation');
input.dispatchEvent(event);
expect(spy).to.have.been.calledOnce;
});
// production code
[...]
input.addEventListener('focus',
function(e) {
e.stopPropagation();
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
User interaction / events
// tests
it('should stop event propagation',
function() {
[...]
var event = new Event('focus');
var spy = sinon.spy(event,
'stopPropagation');
input.dispatchEvent(event);
expect(spy).to.have.been.calledOnce;
});
// production code
[...]
input.addEventListener('focus',
function(e) {
e.stopPropagation();
var element =
document.createElement('div');
element.id = 'datePicker';
document.body.appendChild(element);
}
[...]
✓
Manipulating the DOM
// tests
it('should add class "selected" on a day when it is clicked',
function(){
});
Manipulating the DOM
// tests
it('should add class "selected" on a day when it is clicked',
function(){
[...]
var day = document.querySelector('#datePicker .day');
day.click();
});
Manipulating the DOM
// tests
it('adds class "selected" on a day when clicked', function() {
[...]
var day = document.querySelector('#datePicker .day');
day.click();
var i = day.className.indexOf('selected');
expect(i > -1).to.be.true;
});
Mocking Time, tick tick tick
// tests
Mocking Time
// tests
it('should hide datePicker after 300ms', function(){
[...]
var clock = sinon.useFakeTimers();
day.click();
clock.tick(299);
expect(datePicker.className.indexOf('hidden') > -1).to.be.false;
clock.tick(2);
expect(datePicker.className.indexOf('hidden') > -1).to.be.true;
clock.restore();
});
Mocking Browser methods
// tests
Mocking Browser methods
// tests
beforeEach(function() {
this.dateNowStub = sinon.stub(Date, 'now', function() {
return new Date('2016-01-13').getTime();
});
});
afterEach(function(){
this.dateNowStub.restore();
});
Testing Javascript for the Browser
In a browser
Take it to the next level
Headless browser testing (phantomjs, zombie, electron...)
Continuous Integration: automate your tests in jenkins, travis…
A few more tips
- Find a BUG ? Write a TEST!
- Do TDD while PAIRING
- Use the Web APIs in your TESTS
- Don’t try to test the browser
- You don’t need to test libraries
THANK YOU
And HAPPY Testing!

More Related Content

What's hot

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
 
Testing JS with Jasmine
Testing JS with JasmineTesting JS with Jasmine
Testing JS with JasmineEvgeny Gurin
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and JasmineAngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasminefoxp2code
 
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
 
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
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSJim Lynch
 
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
 
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
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSKnoldus Inc.
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsFITC
 
Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Fwdays
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJSPeter Drinnan
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsYnon Perek
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpAll Things Open
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit TestChiew Carol
 

What's hot (20)

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
 
Testing JS with Jasmine
Testing JS with JasmineTesting JS with Jasmine
Testing JS with Jasmine
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and JasmineAngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasmine
 
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
 
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
 
Jasmine BDD for Javascript
Jasmine BDD for JavascriptJasmine BDD for Javascript
Jasmine BDD for Javascript
 
Night Watch with QA
Night Watch with QANight Watch with QA
Night Watch with QA
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
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
 
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
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
 
Angular testing
Angular testingAngular testing
Angular testing
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
 
Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJS
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and Gulp
 
PL/SQL Unit Testing Can Be Fun!
PL/SQL Unit Testing Can Be Fun!PL/SQL Unit Testing Can Be Fun!
PL/SQL Unit Testing Can Be Fun!
 
Vuejs testing
Vuejs testingVuejs testing
Vuejs testing
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit Test
 

Viewers also liked

The Developer Experience
The Developer ExperienceThe Developer Experience
The Developer ExperienceAtlassian
 
Unit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with JasmineUnit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with JasmineKeir Bowden
 
Developer Experience to Testing
Developer Experience to TestingDeveloper Experience to Testing
Developer Experience to TestingMozaic Works
 
JavaScript Unit Testing
JavaScript Unit TestingJavaScript Unit Testing
JavaScript Unit TestingKeir Bowden
 
Introducing Sencha Touch 2
Introducing Sencha Touch 2Introducing Sencha Touch 2
Introducing Sencha Touch 2Sencha
 
How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016
How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016
How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016Gavin Pickin
 
Javascript testing: tools of the trade
Javascript testing: tools of the tradeJavascript testing: tools of the trade
Javascript testing: tools of the tradeJuanma Orta
 
Javascript Unit Testing Tools
Javascript Unit Testing ToolsJavascript Unit Testing Tools
Javascript Unit Testing ToolsPixelCrayons
 
JAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & JasmineJAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & JasmineAnup Singh
 
Unit-testing and E2E testing in JS
Unit-testing and E2E testing in JSUnit-testing and E2E testing in JS
Unit-testing and E2E testing in JSMichael Haberman
 
SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...
SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...
SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...Sencha
 
Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"
Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"
Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"Fwdays
 

Viewers also liked (13)

The Developer Experience
The Developer ExperienceThe Developer Experience
The Developer Experience
 
Unit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with JasmineUnit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with Jasmine
 
Developer Experience to Testing
Developer Experience to TestingDeveloper Experience to Testing
Developer Experience to Testing
 
JavaScript Unit Testing
JavaScript Unit TestingJavaScript Unit Testing
JavaScript Unit Testing
 
Introducing Sencha Touch 2
Introducing Sencha Touch 2Introducing Sencha Touch 2
Introducing Sencha Touch 2
 
How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016
How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016
How do I write Testable Javascript - Presented at dev.Objective() June 16, 2016
 
Javascript testing: tools of the trade
Javascript testing: tools of the tradeJavascript testing: tools of the trade
Javascript testing: tools of the trade
 
Javascript Unit Testing Tools
Javascript Unit Testing ToolsJavascript Unit Testing Tools
Javascript Unit Testing Tools
 
JAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & JasmineJAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & Jasmine
 
Unit-testing and E2E testing in JS
Unit-testing and E2E testing in JSUnit-testing and E2E testing in JS
Unit-testing and E2E testing in JS
 
SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...
SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...
SenchaCon 2016: The Changing Landscape of JavaScript Testing - Joel Watson an...
 
jasmine
jasminejasmine
jasmine
 
Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"
Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"
Михаил Боднарчук "Acceptance Testing in NodeJS: Tools & Approaches"
 

Similar to Testing javascript in the frontend

Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]JavaScript Meetup HCMC
 
The Open Web and what it means
The Open Web and what it meansThe Open Web and what it means
The Open Web and what it meansRobert Nyman
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS ArchitectureEyal Vardi
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS InternalEyal Vardi
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Davide Cerbo
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming Enguest9bcef2f
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suckRoss Bruniges
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 
Building Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksBuilding Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksMike Hugo
 
Desafios do Profissionalismo Ágil
Desafios do Profissionalismo ÁgilDesafios do Profissionalismo Ágil
Desafios do Profissionalismo ÁgilVictor Hugo Germano
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2Paras Mendiratta
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsAdégòkè Obasá
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingVisual Engineering
 
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Codemotion
 
JavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the PlatformJavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the PlatformRobert Nyman
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 

Similar to Testing javascript in the frontend (20)

Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]
 
The Open Web and what it means
The Open Web and what it meansThe Open Web and what it means
The Open Web and what it means
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
Building Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksBuilding Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And Tricks
 
A Test of Strength
A Test of StrengthA Test of Strength
A Test of Strength
 
Desafios do Profissionalismo Ágil
Desafios do Profissionalismo ÁgilDesafios do Profissionalismo Ágil
Desafios do Profissionalismo Ágil
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web Apps
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
 
JavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the PlatformJavaScript APIs - The Web is the Platform
JavaScript APIs - The Web is the Platform
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 

Recently uploaded

React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 

Recently uploaded (20)

React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 

Testing javascript in the frontend

  • 1. Testing Javascript from a Frontend perspective Frederic Cabassut - Campanda
  • 2. The basics of test-driven development
  • 3. TDD Cycle - Rule #1 You must write a failing test before you write any production code.
  • 4. TDD Cycle - Rule #2 You must not write more of a test than is sufficient to fail, or fail to compile.
  • 5. TDD Cycle - Rule #3 You must not write more production code than is sufficient to make the currently failing test pass.
  • 6. TDD Cycle // tests // production code
  • 7. TDD Cycle // tests var expected = "Hello, Fred!"; // production code
  • 8. TDD Cycle // tests var expected = "Hello, Fred!"; // production code ✓
  • 9. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code
  • 10. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code Uncaught ReferenceError: getMyObj is not defined
  • 11. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code function getMyObj() { }
  • 12. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code function getMyObj() { } Uncaught TypeError: Cannot read property 'greet' of undefined
  • 13. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code function getMyObj() { return {}; }
  • 14. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code function getMyObj() { return {}; } Uncaught TypeError: getMyObj(...).greet is not a function
  • 15. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code function getMyObj() { return { greet: function() { } }; } }
  • 16. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); // production code function getMyObj() { return { greet: function () { } }; } ✓
  • 17. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); assert.equal(expected, actual); // production code function getMyObj() { return { greet: function() { } }; }
  • 18. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); assert.equal(expected, actual); // production code function getMyObj() { return { greet: function() { } }; } AssertionError: "Hello, Fred!" == undefined
  • 19. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); assert.equal(expected, actual); // production code function getMyObj() { return { greet: function() { return "Hello, Fred!"; } }; }
  • 20. TDD Cycle // tests var expected = "Hello, Fred!"; var actual = getMyObj().greet("Fred"); assert.equal(expected, actual); // production code function getMyObj() { return { greet: function() { return "Hello, Fred!"; } }; } ✓
  • 21. Why Testing ? - Increase code quality - Deploy with confidence - Self-explaining documentation - Easy to refactor
  • 22. What do we have to test ? - User interaction / events - Manipulating the DOM - Client-side business logic - Ajax request (retrieve/send data)
  • 23. My favorite testing stack: - Mochajs https://mochajs.org/ - Chaijs http://chaijs.com/ - Sinonjs: http://sinonjs.org/ - My browser (+ livereload)
  • 24. Let’s create a DatePicker!
  • 25. Let’s create a DatePicker!
  • 26. Let’s create a DatePicker!
  • 27. Let’s create a DatePicker!
  • 28. Let’s create a DatePicker!
  • 29. User interaction / events // tests it('should initialize a datepicker with a given element', function() { var input = document.createElement('input'); DatePicker.init(input); }); // production code window.DatePicker = { init: function() {} }
  • 30. User interaction / events // tests it('should initialize a datepicker with a given element', function() { var input = document.createElement('input'); DatePicker.init(input); }); // production code window.DatePicker = { init: function() {} } ✓
  • 31. User interaction / events // tests it('should show a datepicker on input focus', function() { }); // production code window.DatePicker = { init: function() {} }
  • 32. User interaction / events // tests it('should show a datepicker on input focus', function() { var input = document.createElement('input'); DatePicker.init(input); }); // production code window.DatePicker = { init: function() {} }
  • 33. User interaction / events // tests it('should show a datepicker on input focus', function() { var input = document.createElement('input'); DatePicker.init(input); }); // production code window.DatePicker = { init: function() {} } ✓
  • 34. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] }); // production code window.DatePicker = { init: function() {} }
  • 35. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); }); // production code window.DatePicker = { init: function() {} }
  • 36. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); }); // production code window.DatePicker = { init: function() {} } ✓
  • 37. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); var element = document.getElementById('datePicker'); expect(element).to.be.ok; }); // production code window.DatePicker = { init: function() {} }
  • 38. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); var element = document.getElementById('datePicker'); expect(element).to.be.ok; }); // production code window.DatePicker = { init: function() {} } AssertionError: expected null to be truthy
  • 39. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); var element = document.getElementById('datePicker'); expect(element).to.be.ok; }); // production code window.DatePicker = { init: function(input) { [...] } }
  • 40. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); var element = document.getElementById('datePicker'); expect(element).to.be.ok; }); // production code [...] input.addEventListener('focus', function() { var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...]
  • 41. User interaction / events // tests it('should show a datepicker on input focus', function() { [...] var event = new Event('focus'); input.dispatchEvent(event); var element = document.getElementById('datePicker'); expect(element).to.be.ok; }); // production code [...] input.addEventListener('focus', function() { var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...] ✓
  • 42. User interaction / events // tests it('should stop event propagation', function() { }); // production code [...] input.addEventListener('focus', function() { var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...]
  • 43. User interaction / events // tests it('should stop event propagation', function() { [...] var event = new Event('focus'); var spy = sinon.spy(event, 'stopPropagation'); input.dispatchEvent(event); expect(spy).to.have.been.calledOnce; }); // production code [...] input.addEventListener('focus', function() { var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...]
  • 44. User interaction / events // tests it('should stop event propagation', function() { [...] var event = new Event('focus'); var spy = sinon.spy(event, 'stopPropagation'); input.dispatchEvent(event); expect(spy).to.have.been.calledOnce; }); // production code [...] input.addEventListener('focus', function() { var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...] expected stopPropagation to have been called exactly once ...
  • 45. User interaction / events // tests it('should stop event propagation', function() { [...] var event = new Event('focus'); var spy = sinon.spy(event, 'stopPropagation'); input.dispatchEvent(event); expect(spy).to.have.been.calledOnce; }); // production code [...] input.addEventListener('focus', function(e) { e.stopPropagation(); var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...]
  • 46. User interaction / events // tests it('should stop event propagation', function() { [...] var event = new Event('focus'); var spy = sinon.spy(event, 'stopPropagation'); input.dispatchEvent(event); expect(spy).to.have.been.calledOnce; }); // production code [...] input.addEventListener('focus', function(e) { e.stopPropagation(); var element = document.createElement('div'); element.id = 'datePicker'; document.body.appendChild(element); } [...] ✓
  • 47. Manipulating the DOM // tests it('should add class "selected" on a day when it is clicked', function(){ });
  • 48. Manipulating the DOM // tests it('should add class "selected" on a day when it is clicked', function(){ [...] var day = document.querySelector('#datePicker .day'); day.click(); });
  • 49. Manipulating the DOM // tests it('adds class "selected" on a day when clicked', function() { [...] var day = document.querySelector('#datePicker .day'); day.click(); var i = day.className.indexOf('selected'); expect(i > -1).to.be.true; });
  • 50. Mocking Time, tick tick tick // tests
  • 51. Mocking Time // tests it('should hide datePicker after 300ms', function(){ [...] var clock = sinon.useFakeTimers(); day.click(); clock.tick(299); expect(datePicker.className.indexOf('hidden') > -1).to.be.false; clock.tick(2); expect(datePicker.className.indexOf('hidden') > -1).to.be.true; clock.restore(); });
  • 53. Mocking Browser methods // tests beforeEach(function() { this.dateNowStub = sinon.stub(Date, 'now', function() { return new Date('2016-01-13').getTime(); }); }); afterEach(function(){ this.dateNowStub.restore(); });
  • 54. Testing Javascript for the Browser In a browser
  • 55. Take it to the next level Headless browser testing (phantomjs, zombie, electron...) Continuous Integration: automate your tests in jenkins, travis…
  • 56. A few more tips - Find a BUG ? Write a TEST! - Do TDD while PAIRING - Use the Web APIs in your TESTS - Don’t try to test the browser - You don’t need to test libraries