SlideShare a Scribd company logo
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 (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
Christopher Bartling
 
Testing JS with Jasmine
Testing JS with JasmineTesting JS with Jasmine
Testing JS with Jasmine
Evgeny 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 Jasmine
foxp2code
 
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
Gil 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 fishy
Igor Napierala
 
Jasmine BDD for Javascript
Jasmine BDD for JavascriptJasmine BDD for Javascript
Jasmine BDD for Javascript
Luis Alfredo Porras Páez
 
Night Watch with QA
Night Watch with QANight Watch with QA
Night Watch with QA
Carsten Sandtner
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
Jim 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 Development
All 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 Karma
Andrey Kolodnitsky
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
Knoldus Inc.
 
Angular testing
Angular testingAngular testing
Angular testing
Raissa Ferreira
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
FITC
 
Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"
Fwdays
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJS
Peter Drinnan
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
Ynon 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 Gulp
All Things Open
 
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!
Raimonds Simanovskis
 
Vuejs testing
Vuejs testingVuejs testing
Vuejs testing
Greg TAPPERO
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit Test
Chiew Carol
 
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 Jasmine
Evgeny 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 Jasmine
foxp2code
 
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
Gil 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 fishy
Igor Napierala
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
Jim 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 Development
All 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 Karma
Andrey Kolodnitsky
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
Knoldus Inc.
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
FITC
 
Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"Сергей Больщиков "Protractor Tips & Tricks"
Сергей Больщиков "Protractor Tips & Tricks"
Fwdays
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJS
Peter Drinnan
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
Ynon 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 Gulp
All Things Open
 
AngularJS Unit Test
AngularJS Unit TestAngularJS Unit Test
AngularJS Unit Test
Chiew Carol
 

Viewers also liked (13)

The Developer Experience
The Developer ExperienceThe Developer Experience
The Developer Experience
Atlassian
 
Unit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with JasmineUnit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with Jasmine
Keir Bowden
 
Developer Experience to Testing
Developer Experience to TestingDeveloper Experience to Testing
Developer Experience to Testing
Mozaic Works
 
JavaScript Unit Testing
JavaScript Unit TestingJavaScript Unit Testing
JavaScript Unit Testing
Keir Bowden
 
Introducing Sencha Touch 2
Introducing Sencha Touch 2Introducing Sencha Touch 2
Introducing Sencha Touch 2
Sencha
 
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
Gavin Pickin
 
Javascript testing: tools of the trade
Javascript testing: tools of the tradeJavascript testing: tools of the trade
Javascript testing: tools of the trade
Juanma Orta
 
Javascript Unit Testing Tools
Javascript Unit Testing ToolsJavascript Unit Testing Tools
Javascript Unit Testing Tools
PixelCrayons
 
JAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & JasmineJAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & Jasmine
Anup 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 JS
Michael 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
 
jasmine
jasminejasmine
jasmine
Asanka Indrajith
 
Михаил Боднарчук "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
 
The Developer Experience
The Developer ExperienceThe Developer Experience
The Developer Experience
Atlassian
 
Unit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with JasmineUnit Testing Lightning Components with Jasmine
Unit Testing Lightning Components with Jasmine
Keir Bowden
 
Developer Experience to Testing
Developer Experience to TestingDeveloper Experience to Testing
Developer Experience to Testing
Mozaic Works
 
JavaScript Unit Testing
JavaScript Unit TestingJavaScript Unit Testing
JavaScript Unit Testing
Keir Bowden
 
Introducing Sencha Touch 2
Introducing Sencha Touch 2Introducing Sencha Touch 2
Introducing Sencha Touch 2
Sencha
 
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
Gavin Pickin
 
Javascript testing: tools of the trade
Javascript testing: tools of the tradeJavascript testing: tools of the trade
Javascript testing: tools of the trade
Juanma Orta
 
Javascript Unit Testing Tools
Javascript Unit Testing ToolsJavascript Unit Testing Tools
Javascript Unit Testing Tools
PixelCrayons
 
JAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & JasmineJAVASCRIPT Test Driven Development & Jasmine
JAVASCRIPT Test Driven Development & Jasmine
Anup 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 JS
Michael 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
 
Ad

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]
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 means
Robert Nyman
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
Eyal Vardi
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
Eyal Vardi
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
guest9bcef2f
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)
Davide Cerbo
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
Ross Bruniges
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
Ryunosuke SATO
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
rajivmordani
 
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 Tricks
Mike Hugo
 
A Test of Strength
A Test of StrengthA Test of Strength
A Test of Strength
Chris Oldwood
 
Desafios do Profissionalismo Ágil
Desafios do Profissionalismo ÁgilDesafios do Profissionalismo Ágil
Desafios do Profissionalismo Ágil
Victor Hugo Germano
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2
Paras 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 Apps
Adégòkè Obasá
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
Michael Girouard
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
Visual 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 2015
Codemotion
 
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
Robert 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 tek12
Michelangelo van Dam
 
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 means
Robert Nyman
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
Eyal Vardi
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
Eyal Vardi
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
guest9bcef2f
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)
Davide Cerbo
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
Ross Bruniges
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
rajivmordani
 
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 Tricks
Mike Hugo
 
Desafios do Profissionalismo Ágil
Desafios do Profissionalismo ÁgilDesafios do Profissionalismo Ágil
Desafios do Profissionalismo Ágil
Victor Hugo Germano
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2
Paras 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 Apps
Adé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 testing
Visual 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 2015
Codemotion
 
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
Robert 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 tek12
Michelangelo van Dam
 
Ad

Recently uploaded (20)

Who will create the languages of the future?
Who will create the languages of the future?Who will create the languages of the future?
Who will create the languages of the future?
Jordi Cabot
 
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
Neuralink TemplateeeeeeeeeeeeeeeeeeeeeeeeeeNeuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
alexandernoetzold
 
Integration Ignited Redefining Event-Driven Architecture at Wix - EventCentric
Integration Ignited Redefining Event-Driven Architecture at Wix - EventCentricIntegration Ignited Redefining Event-Driven Architecture at Wix - EventCentric
Integration Ignited Redefining Event-Driven Architecture at Wix - EventCentric
Natan Silnitsky
 
Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...
Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...
Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...
WSO2
 
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Alluxio, Inc.
 
Integrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FMEIntegrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FME
Safe Software
 
wAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptxwAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptx
SimonedeGijt
 
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Natan Silnitsky
 
AI and Deep Learning with NVIDIA Technologies
AI and Deep Learning with NVIDIA TechnologiesAI and Deep Learning with NVIDIA Technologies
AI and Deep Learning with NVIDIA Technologies
SandeepKS52
 
Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...
Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...
Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...
BradBedford3
 
Best Inbound Call Tracking Software for Small Businesses
Best Inbound Call Tracking Software for Small BusinessesBest Inbound Call Tracking Software for Small Businesses
Best Inbound Call Tracking Software for Small Businesses
TheTelephony
 
Plooma is a writing platform to plan, write, and shape books your way
Plooma is a writing platform to plan, write, and shape books your wayPlooma is a writing platform to plan, write, and shape books your way
Plooma is a writing platform to plan, write, and shape books your way
Plooma
 
Shell Skill Tree - LabEx Certification (LabEx)
Shell Skill Tree - LabEx Certification (LabEx)Shell Skill Tree - LabEx Certification (LabEx)
Shell Skill Tree - LabEx Certification (LabEx)
VICTOR MAESTRE RAMIREZ
 
FME for Climate Data: Turning Big Data into Actionable Insights
FME for Climate Data: Turning Big Data into Actionable InsightsFME for Climate Data: Turning Big Data into Actionable Insights
FME for Climate Data: Turning Big Data into Actionable Insights
Safe Software
 
Agile Software Engineering Methodologies
Agile Software Engineering MethodologiesAgile Software Engineering Methodologies
Agile Software Engineering Methodologies
Gaurav Sharma
 
Providing Better Biodiversity Through Better Data
Providing Better Biodiversity Through Better DataProviding Better Biodiversity Through Better Data
Providing Better Biodiversity Through Better Data
Safe Software
 
Essentials of Resource Planning in a Downturn
Essentials of Resource Planning in a DownturnEssentials of Resource Planning in a Downturn
Essentials of Resource Planning in a Downturn
OnePlan Solutions
 
How Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines OperationsHow Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines Operations
Insurance Tech Services
 
Revolutionize Your Insurance Workflow with Claims Management Software
Revolutionize Your Insurance Workflow with Claims Management SoftwareRevolutionize Your Insurance Workflow with Claims Management Software
Revolutionize Your Insurance Workflow with Claims Management Software
Insurance Tech Services
 
Automating Map Production With FME and Python
Automating Map Production With FME and PythonAutomating Map Production With FME and Python
Automating Map Production With FME and Python
Safe Software
 
Who will create the languages of the future?
Who will create the languages of the future?Who will create the languages of the future?
Who will create the languages of the future?
Jordi Cabot
 
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
Neuralink TemplateeeeeeeeeeeeeeeeeeeeeeeeeeNeuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
alexandernoetzold
 
Integration Ignited Redefining Event-Driven Architecture at Wix - EventCentric
Integration Ignited Redefining Event-Driven Architecture at Wix - EventCentricIntegration Ignited Redefining Event-Driven Architecture at Wix - EventCentric
Integration Ignited Redefining Event-Driven Architecture at Wix - EventCentric
Natan Silnitsky
 
Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...
Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...
Build Smarter, Deliver Faster with Choreo - An AI Native Internal Developer P...
WSO2
 
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Alluxio, Inc.
 
Integrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FMEIntegrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FME
Safe Software
 
wAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptxwAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptx
SimonedeGijt
 
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Natan Silnitsky
 
AI and Deep Learning with NVIDIA Technologies
AI and Deep Learning with NVIDIA TechnologiesAI and Deep Learning with NVIDIA Technologies
AI and Deep Learning with NVIDIA Technologies
SandeepKS52
 
Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...
Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...
Maintaining + Optimizing Database Health: Vendors, Orchestrations, Enrichment...
BradBedford3
 
Best Inbound Call Tracking Software for Small Businesses
Best Inbound Call Tracking Software for Small BusinessesBest Inbound Call Tracking Software for Small Businesses
Best Inbound Call Tracking Software for Small Businesses
TheTelephony
 
Plooma is a writing platform to plan, write, and shape books your way
Plooma is a writing platform to plan, write, and shape books your wayPlooma is a writing platform to plan, write, and shape books your way
Plooma is a writing platform to plan, write, and shape books your way
Plooma
 
Shell Skill Tree - LabEx Certification (LabEx)
Shell Skill Tree - LabEx Certification (LabEx)Shell Skill Tree - LabEx Certification (LabEx)
Shell Skill Tree - LabEx Certification (LabEx)
VICTOR MAESTRE RAMIREZ
 
FME for Climate Data: Turning Big Data into Actionable Insights
FME for Climate Data: Turning Big Data into Actionable InsightsFME for Climate Data: Turning Big Data into Actionable Insights
FME for Climate Data: Turning Big Data into Actionable Insights
Safe Software
 
Agile Software Engineering Methodologies
Agile Software Engineering MethodologiesAgile Software Engineering Methodologies
Agile Software Engineering Methodologies
Gaurav Sharma
 
Providing Better Biodiversity Through Better Data
Providing Better Biodiversity Through Better DataProviding Better Biodiversity Through Better Data
Providing Better Biodiversity Through Better Data
Safe Software
 
Essentials of Resource Planning in a Downturn
Essentials of Resource Planning in a DownturnEssentials of Resource Planning in a Downturn
Essentials of Resource Planning in a Downturn
OnePlan Solutions
 
How Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines OperationsHow Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines Operations
Insurance Tech Services
 
Revolutionize Your Insurance Workflow with Claims Management Software
Revolutionize Your Insurance Workflow with Claims Management SoftwareRevolutionize Your Insurance Workflow with Claims Management Software
Revolutionize Your Insurance Workflow with Claims Management Software
Insurance Tech Services
 
Automating Map Production With FME and Python
Automating Map Production With FME and PythonAutomating Map Production With FME and Python
Automating Map Production With FME and Python
Safe Software
 

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