SlideShare a Scribd company logo
1 of 26
Download to read offline
Writing testable JS
by Ted Piotrowski
Javascript Ho Chi Minh City
Excuses for not testing
● I know the code
● Test suite is hard to configure and run
● You can’t test UI
● You can’t unit test JS code
$(document).ready(function() {
$('#new-status form').submit(function(e) {
e.preventDefault();
$.ajax({
url: '/status',
type: 'POST',
dataType: 'json',
data: { text: $('#new-status').find('textarea').val() },
success: function(data) {
$('#statuses').append('<li>' + data.text + '</li>');
$('#new-status').find('textarea').val('');
}
});
});
});
source: https://github.com/kjbekkelund/writings/blob/master/published/understanding-backbone.md/
Documentation
● Impossible to write a good test without a
good specification
● If you don’t have time to write a test, at least
write documentation
○ it will allow others to write tests later
/**
* adds two numbers together
*/
function sum(a, b)
assert(sum(1, 2), 3);
/**
* adds two numbers together
*/
function sum(a, b)
assert(sum(1, ‘a’), ?);
/**
* adds two numbers together,
* otherwise returns null
*/
function sum(a, b)
assert(sum(1, ‘a’), null);
Dependencies
● Can’t write good tests unless you
understand what external objects the code
depends on
● loose coupling
● use requirejs, almond.js, squire.js
● move dependencies up the call stack and
inject
Scope
● An assertion should only rely on the method
being tested
● What is a “unit”?
● is $(function() { }) a unit?
// Should we stub addTwo, addOne?
// When we limit scope, we forfeit integration
function addThree(a) {
var x = addTwo(a);
var y = addOne(x);
return y;
}
Testing with the DOM
● Use a DOM fragment / jQuery fragment
● Inject it into the module constructor
function Word() {
this.el = $('.word'); // external dependency
}
Word.prototype.setText = function(text) {
this.el.text(text);
};
var word = new Word();
word.setText('Hello World');
assert(???, 'Hello World');
function Word(el) {
this.el = el; // dependency injection
}
Word.prototype.setText = function(text) {
this.el.text(text);
};
var mockEl = $('<div></div>'); // use a test double
var word = new Word(mockEl); // inject the dependency
word.setText('Hello World');
assert(mockEl.text(), 'Hello World');
function Word(el) {
this.el = el || $('.word'); // optional injection
}
Word.prototype.setText = function(text) {
this.el.text(text);
};
var mockEl = $('<div></div>');
var word = new Word(mockEl);
word.setText('Hello World');
assert(mockEl.text(), 'Hello World');
Dealing with window properties
● You code will likely touch Web API
○ document, Math,
● Can use mocks and stubs for methods
● Many Web API properties are read-only
// If your production code calls alert(), you can mock it
var spy = sinon.spy(window, "alert");
assert(spy.calledWith("My alert message"));
// However, you can't modify read only properties
Math.PI = 3.15; // won’t work
window.History.length = 12;
function Win(windowObj) {
this.window = windowObj || window;
}
Win.prototype.scrollX = function() { return this.window.scrollX };
Win.prototype.scrollY = function() { return this.window.scrollY };
var win = new Win(); // in production
// win.scrollX() => actual value
var win = new Win({ // in testing
scrollX: 50, scrollY: 40, History: { … }
}); // win.scrollX() => 50
Dealing with network calls
● Use sinon fake server
{
"test should fetch comments from server" : function () {
this.server.respondWith("GET", "/some/article/comments.json",
[200, { "Content-Type": "application/json" },
'[{ "id": 12, "comment": "Hey there" }]']);
var callback = sinon.spy();
myLib.getCommentsFor("/some/article", callback);
this.server.respond();
sinon.assert.calledWith(callback, [{ id: 12, comment: "Hey there" }]));
}
}
Code coverage
● Reports what lines of production JS are
executed during testing
● necessary, but not sufficient
● Istanbul is a good tool
○ integrates with Karma
JS integration tests
● main.js file initializes your components and
injects DOM dependencies
● Stub your REST calls
● Just like unit testing, user events are your
input, DOM changes are your output
// Bootstrap your application here
// Inject your DOM dependencies at top of call stack
// Allows you to mock/stub the DOM for each component
$(function() {
var $el = $('.some-element');
var component = new Component($el);
var $el2 = $('.some-element2');
var component2 = new Component($el2);
// initialize more components, global state here
});
Demo time
More information
● Testable Javascript
● Karma test runner
● Sinon.js
● Istanbul
About us
Author: Ted Piotrowski
Find me at: tpiotrowski@atlassian.com
Sample code: https://bitbucket.org/tpiotrowski/js-hcm
Presentation made for Javascript Ho Chi Minh City Meetup Group
You can find us at:
● http://www.meetup.com/JavaScript-Ho-Chi-Minh-City/
● https://www.facebook.com/JavaScriptHCMC
● https://plus.google.com/u/0/communities/116105314977285194967
● http://www.slideshare.net/JavascriptMeetup
Lean Coffee
Discussion topics

More Related Content

What's hot

jQuery Bay Area Conference 2010
jQuery Bay Area Conference 2010jQuery Bay Area Conference 2010
jQuery Bay Area Conference 2010mennovanslooten
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSNicolas Embleton
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS InternalEyal Vardi
 
AngularJS $Provide Service
AngularJS $Provide ServiceAngularJS $Provide Service
AngularJS $Provide ServiceEyal Vardi
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesRainer Stropek
 
AngularJS Services
AngularJS ServicesAngularJS Services
AngularJS ServicesEyal Vardi
 
10 tips for a reusable architecture
10 tips for a reusable architecture10 tips for a reusable architecture
10 tips for a reusable architectureJorge Ortiz
 
Angular js - 4developers 12 kwietnia 2013
Angular js - 4developers 12 kwietnia 2013Angular js - 4developers 12 kwietnia 2013
Angular js - 4developers 12 kwietnia 2013Marcin Wosinek
 
Angular 1.x vs. Angular 2.x
Angular 1.x vs. Angular 2.xAngular 1.x vs. Angular 2.x
Angular 1.x vs. Angular 2.xEyal Vardi
 
Async js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaAsync js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaHackBulgaria
 
Modules and injector
Modules and injectorModules and injector
Modules and injectorEyal Vardi
 
AngularJS Animations
AngularJS AnimationsAngularJS Animations
AngularJS AnimationsEyal Vardi
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IVisual Engineering
 
AngulrJS Overview
AngulrJS OverviewAngulrJS Overview
AngulrJS OverviewEyal Vardi
 
Обзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScriptОбзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScriptCOMAQA.BY
 
Testing JavaScript with Jasmine in Rails Applications
Testing JavaScript with Jasmine in Rails Applications Testing JavaScript with Jasmine in Rails Applications
Testing JavaScript with Jasmine in Rails Applications Hector Correa
 

What's hot (20)

jQuery Bay Area Conference 2010
jQuery Bay Area Conference 2010jQuery Bay Area Conference 2010
jQuery Bay Area Conference 2010
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
AngularJS $Provide Service
AngularJS $Provide ServiceAngularJS $Provide Service
AngularJS $Provide Service
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
 
AngularJS Services
AngularJS ServicesAngularJS Services
AngularJS Services
 
10 tips for a reusable architecture
10 tips for a reusable architecture10 tips for a reusable architecture
10 tips for a reusable architecture
 
Angular js - 4developers 12 kwietnia 2013
Angular js - 4developers 12 kwietnia 2013Angular js - 4developers 12 kwietnia 2013
Angular js - 4developers 12 kwietnia 2013
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
 
Angular 1.x vs. Angular 2.x
Angular 1.x vs. Angular 2.xAngular 1.x vs. Angular 2.x
Angular 1.x vs. Angular 2.x
 
Async js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaAsync js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgaria
 
Modules and injector
Modules and injectorModules and injector
Modules and injector
 
AngularJS Animations
AngularJS AnimationsAngularJS Animations
AngularJS Animations
 
AngularJs
AngularJsAngularJs
AngularJs
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
 
Angularjs Basics
Angularjs BasicsAngularjs Basics
Angularjs Basics
 
Human Talks - StencilJS
Human Talks - StencilJSHuman Talks - StencilJS
Human Talks - StencilJS
 
AngulrJS Overview
AngulrJS OverviewAngulrJS Overview
AngulrJS Overview
 
Обзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScriptОбзор автоматизации тестирования на JavaScript
Обзор автоматизации тестирования на JavaScript
 
Testing JavaScript with Jasmine in Rails Applications
Testing JavaScript with Jasmine in Rails Applications Testing JavaScript with Jasmine in Rails Applications
Testing JavaScript with Jasmine in Rails Applications
 

Similar to Writing testable js [by Ted Piotrowski]

Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascriptaglemann
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
the next web now
the next web nowthe next web now
the next web nowzulin Gu
 
Building High Performance Web Applications and Sites
Building High Performance Web Applications and SitesBuilding High Performance Web Applications and Sites
Building High Performance Web Applications and Sitesgoodfriday
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 
Testing javascript in the frontend
Testing javascript in the frontendTesting javascript in the frontend
Testing javascript in the frontendFrederic CABASSUT
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Yevgeniy Brikman
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bitsChris Saylor
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Murat Yener
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPresswpnepal
 
Good karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaGood karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaExoLeaders.com
 
Sqladria 2009 SRC
Sqladria 2009 SRCSqladria 2009 SRC
Sqladria 2009 SRCtepsum
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSKnoldus Inc.
 
JavaScript straight from the Oracle Database
JavaScript straight from the Oracle DatabaseJavaScript straight from the Oracle Database
JavaScript straight from the Oracle DatabaseDimitri Gielis
 
Automated javascript unit testing
Automated javascript unit testingAutomated javascript unit testing
Automated javascript unit testingryan_chambers
 
Ajax Basics 2
Ajax Basics 2Ajax Basics 2
Ajax Basics 2bhuvanann
 

Similar to Writing testable js [by Ted Piotrowski] (20)

Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascript
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
JavaScript Core
JavaScript CoreJavaScript Core
JavaScript Core
 
the next web now
the next web nowthe next web now
the next web now
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
 
Building High Performance Web Applications and Sites
Building High Performance Web Applications and SitesBuilding High Performance Web Applications and Sites
Building High Performance Web Applications and Sites
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
Testing javascript in the frontend
Testing javascript in the frontendTesting javascript in the frontend
Testing javascript in the frontend
 
Testing in JavaScript
Testing in JavaScriptTesting in JavaScript
Testing in JavaScript
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPress
 
Good karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaGood karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with Karma
 
Sqladria 2009 SRC
Sqladria 2009 SRCSqladria 2009 SRC
Sqladria 2009 SRC
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
 
JavaScript straight from the Oracle Database
JavaScript straight from the Oracle DatabaseJavaScript straight from the Oracle Database
JavaScript straight from the Oracle Database
 
Automated javascript unit testing
Automated javascript unit testingAutomated javascript unit testing
Automated javascript unit testing
 
Ajax Basics 2
Ajax Basics 2Ajax Basics 2
Ajax Basics 2
 

More from JavaScript Meetup HCMC

Building workflow in Javascript: Build the awesome with Gulp.
Building workflow in Javascript: Build the awesome with Gulp.   Building workflow in Javascript: Build the awesome with Gulp.
Building workflow in Javascript: Build the awesome with Gulp. JavaScript Meetup HCMC
 
[Js hcm] Java script- Testing the awesome
[Js hcm] Java script- Testing the awesome[Js hcm] Java script- Testing the awesome
[Js hcm] Java script- Testing the awesomeJavaScript Meetup HCMC
 
Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...
Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...
Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...JavaScript Meetup HCMC
 
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]JavaScript Meetup HCMC
 
Khanh-Nguyen - Gearman - distributed process solution
Khanh-Nguyen - Gearman - distributed process solutionKhanh-Nguyen - Gearman - distributed process solution
Khanh-Nguyen - Gearman - distributed process solutionJavaScript Meetup HCMC
 
Nicolas-Embleton - Deploying node.js with forever and nginx
Nicolas-Embleton  - Deploying node.js with forever and nginxNicolas-Embleton  - Deploying node.js with forever and nginx
Nicolas-Embleton - Deploying node.js with forever and nginxJavaScript Meetup HCMC
 

More from JavaScript Meetup HCMC (8)

Building workflow in Javascript: Build the awesome with Gulp.
Building workflow in Javascript: Build the awesome with Gulp.   Building workflow in Javascript: Build the awesome with Gulp.
Building workflow in Javascript: Build the awesome with Gulp.
 
[Js hcm] Java script- Testing the awesome
[Js hcm] Java script- Testing the awesome[Js hcm] Java script- Testing the awesome
[Js hcm] Java script- Testing the awesome
 
Knockout js (Dennis Haney)
Knockout js (Dennis Haney)Knockout js (Dennis Haney)
Knockout js (Dennis Haney)
 
Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...
Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...
Debugging JavaScript (by Thomas Bindzus, Founder, Vinagility & Thanh Loc Vo, ...
 
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
 
Nicolas Embleton, Advanced Angular JS
Nicolas Embleton, Advanced Angular JSNicolas Embleton, Advanced Angular JS
Nicolas Embleton, Advanced Angular JS
 
Khanh-Nguyen - Gearman - distributed process solution
Khanh-Nguyen - Gearman - distributed process solutionKhanh-Nguyen - Gearman - distributed process solution
Khanh-Nguyen - Gearman - distributed process solution
 
Nicolas-Embleton - Deploying node.js with forever and nginx
Nicolas-Embleton  - Deploying node.js with forever and nginxNicolas-Embleton  - Deploying node.js with forever and nginx
Nicolas-Embleton - Deploying node.js with forever and nginx
 

Recently uploaded

My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 

Recently uploaded (20)

My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 

Writing testable js [by Ted Piotrowski]

  • 1. Writing testable JS by Ted Piotrowski Javascript Ho Chi Minh City
  • 2. Excuses for not testing ● I know the code ● Test suite is hard to configure and run ● You can’t test UI ● You can’t unit test JS code
  • 3. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type: 'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); } }); }); }); source: https://github.com/kjbekkelund/writings/blob/master/published/understanding-backbone.md/
  • 4. Documentation ● Impossible to write a good test without a good specification ● If you don’t have time to write a test, at least write documentation ○ it will allow others to write tests later
  • 5. /** * adds two numbers together */ function sum(a, b) assert(sum(1, 2), 3);
  • 6. /** * adds two numbers together */ function sum(a, b) assert(sum(1, ‘a’), ?);
  • 7. /** * adds two numbers together, * otherwise returns null */ function sum(a, b) assert(sum(1, ‘a’), null);
  • 8. Dependencies ● Can’t write good tests unless you understand what external objects the code depends on ● loose coupling ● use requirejs, almond.js, squire.js ● move dependencies up the call stack and inject
  • 9. Scope ● An assertion should only rely on the method being tested ● What is a “unit”? ● is $(function() { }) a unit?
  • 10. // Should we stub addTwo, addOne? // When we limit scope, we forfeit integration function addThree(a) { var x = addTwo(a); var y = addOne(x); return y; }
  • 11. Testing with the DOM ● Use a DOM fragment / jQuery fragment ● Inject it into the module constructor
  • 12. function Word() { this.el = $('.word'); // external dependency } Word.prototype.setText = function(text) { this.el.text(text); }; var word = new Word(); word.setText('Hello World'); assert(???, 'Hello World');
  • 13. function Word(el) { this.el = el; // dependency injection } Word.prototype.setText = function(text) { this.el.text(text); }; var mockEl = $('<div></div>'); // use a test double var word = new Word(mockEl); // inject the dependency word.setText('Hello World'); assert(mockEl.text(), 'Hello World');
  • 14. function Word(el) { this.el = el || $('.word'); // optional injection } Word.prototype.setText = function(text) { this.el.text(text); }; var mockEl = $('<div></div>'); var word = new Word(mockEl); word.setText('Hello World'); assert(mockEl.text(), 'Hello World');
  • 15. Dealing with window properties ● You code will likely touch Web API ○ document, Math, ● Can use mocks and stubs for methods ● Many Web API properties are read-only
  • 16. // If your production code calls alert(), you can mock it var spy = sinon.spy(window, "alert"); assert(spy.calledWith("My alert message")); // However, you can't modify read only properties Math.PI = 3.15; // won’t work window.History.length = 12;
  • 17. function Win(windowObj) { this.window = windowObj || window; } Win.prototype.scrollX = function() { return this.window.scrollX }; Win.prototype.scrollY = function() { return this.window.scrollY }; var win = new Win(); // in production // win.scrollX() => actual value var win = new Win({ // in testing scrollX: 50, scrollY: 40, History: { … } }); // win.scrollX() => 50
  • 18. Dealing with network calls ● Use sinon fake server
  • 19. { "test should fetch comments from server" : function () { this.server.respondWith("GET", "/some/article/comments.json", [200, { "Content-Type": "application/json" }, '[{ "id": 12, "comment": "Hey there" }]']); var callback = sinon.spy(); myLib.getCommentsFor("/some/article", callback); this.server.respond(); sinon.assert.calledWith(callback, [{ id: 12, comment: "Hey there" }])); } }
  • 20. Code coverage ● Reports what lines of production JS are executed during testing ● necessary, but not sufficient ● Istanbul is a good tool ○ integrates with Karma
  • 21. JS integration tests ● main.js file initializes your components and injects DOM dependencies ● Stub your REST calls ● Just like unit testing, user events are your input, DOM changes are your output
  • 22. // Bootstrap your application here // Inject your DOM dependencies at top of call stack // Allows you to mock/stub the DOM for each component $(function() { var $el = $('.some-element'); var component = new Component($el); var $el2 = $('.some-element2'); var component2 = new Component($el2); // initialize more components, global state here });
  • 24. More information ● Testable Javascript ● Karma test runner ● Sinon.js ● Istanbul
  • 25. About us Author: Ted Piotrowski Find me at: tpiotrowski@atlassian.com Sample code: https://bitbucket.org/tpiotrowski/js-hcm Presentation made for Javascript Ho Chi Minh City Meetup Group You can find us at: ● http://www.meetup.com/JavaScript-Ho-Chi-Minh-City/ ● https://www.facebook.com/JavaScriptHCMC ● https://plus.google.com/u/0/communities/116105314977285194967 ● http://www.slideshare.net/JavascriptMeetup