SlideShare a Scribd company logo
Front End Workshops
VI.JavaScript testing. Client vs.
Server testing. Test Driven
Development
Raúl Delgado Astudillo
rdelgado@visual-engin.com
Mario García Martín
mgarcia@visual-engin.com
JavaScript testing
“Testing is an infinite process of comparing the invisible to the
ambiguous in order to avoid the unthinkable happening to the
anonymous.”
— James Bach
What is a test?
Type some code
Open and load the browser
Prove functionality
A test is (simply) the validation of an expectation.
Manual testing...
...is
NOT
enough!
Can we do better?
Manual testing is...
Time consuming
Error prone
Irreproducible
(Nearly) Impossible if we want to test a
wide set of browsers and platforms
YES!!
Automated
testing
Tests should be
Fast to run
Easy to understand
Isolated
Not reliant on an Internet connection
Benefits and pitfalls of testing
Regression testing
Refactoring
Cross-browser testing
Good documentation
Helps us write cleaner
interfaces (testable code)
Writing good tests can be
challenging
More information in...
● Test-Driven JavaScript Development, by Christian Johansen
● https://en.wikipedia.org/wiki/Software_testing
Client testing
“A passing test doesn't mean no problem. It means no problem
observed. This time. With these inputs. So far. On my machine.”
— Michael Bolton
Frameworks
Jasmine — Scaffolding
describe("A suite with setup and tear-down", function() {
var foo;
beforeAll(function() {});
afterAll(function() {});
beforeEach(function() {
foo = 1;
});
afterEach(function() {
foo = 0;
});
it("can contain specs with one or more expectations", function() {
expect(foo).toBe(1);
expect(true).toBe(true);
});
});
Matchers
expect(3).toBe(3); // Compares with ===
expect({a: 3}).toEqual({a: 3}); // For comparison of objects
expect('barely').toMatch(/bar/); // For regular expressions
expect(null).toBeDefined(); // Compares against undefined
expect(undefined).toBeUndefined(); // Compares against undefined
expect(null).toBeNull(); // Compares against null
expect('hello').toBeTruthy(); // For boolean casting testing
expect('').toBeFalsy(); // For boolean casting testing
expect(['bar', 'foo']).toContain('bar'); // For finding an item in an Array
expect(2).toBeLessThan(3); // For mathematical comparisons
expect(3).toBeGreaterThan(2); // For mathematical comparisons
expect(3.14).toBeCloseTo(3.17, 1); // For precision math comparison
// For testing if a function throws an exception
expect(function() { throw new Error('Error!'); }).toThrow();
// Modifier 'not'
expect(false).not.toBe(true);
Spies
describe("A suite", function() {
var foo, bar = null;
beforeEach(function() {
foo = { setBar: function(value) { bar = value; } };
spyOn(foo, 'setBar');
foo.setBar(123);
foo.setBar(456, 'another param');
});
it("that defines a spy out of the box", function() {
expect(foo.setBar).toHaveBeenCalled(); // tracks that the spy was called
// tracks all the arguments of its calls
expect(foo.setBar).toHaveBeenCalledWith(123);
expect(foo.setBar).toHaveBeenCalledWith(456, 'another param');
expect(bar).toBeNull(); // stops all execution on a function
});
});
Spies — and.callthrough
describe("A suite", function() {
var foo, bar = null;
beforeEach(function() {
foo = {
setBar: function(value) { bar = value; }
};
spyOn(foo, 'setBar').and.callThrough();
foo.setBar(123);
});
it("that defines a spy configured to call through", function() {
expect(foo.setBar).toHaveBeenCalled(); // tracks that the spy was called
expect(bar).toEqual(123); // the spied function has been called
});
});
describe("A suite", function() {
var foo, bar = null;
beforeEach(function() {
foo = {
getBar: function() { return bar; }
};
spyOn(foo, 'getBar').and.returnValue(745);
});
it("that defines a spy configured to fake a return value", function() {
expect(foo.getBar()).toBe(745); // when called returns the requested value
expect(bar).toBeNull(); // should not affect the variable
});
});
Spies — and.returnValue
describe("A suite", function() {
var foo, bar = null;
beforeEach(function() {
foo = {
setBar: function(value) { bar = value; }
};
spyOn(foo, 'setBar').and.callFake(function() {
console.log('hello');
});
foo.setBar(); // logs hello in the console.
});
it("that defines a spy configured with an alternate implementation", function() {
expect(foo.setBar).toHaveBeenCalled(); // tracks that the spy was called
expect(bar).toBeNull(); // should not affect the variable
});
});
Spies — and.callFake
Spies — createSpy
describe("A suite", function() {
var spy;
beforeAll(function() {
$(window).on('resize', function() { $(window).trigger('myEvent'); });
});
afterAll(function() {
$(window).off('resize');
});
beforeEach(function() {
spy = jasmine.createSpy();
});
it("that defines a spy created manually", function() {
$(window).on('myEvent', spy);
$(window).trigger('resize');
expect(spy).toHaveBeenCalled(); // tracks that the spy was called
});
});
Spies — Other tracking properties (I)
describe("A spy", function() {
var foo, bar = null;
beforeEach(function() {
foo = { setBar: function(value) { bar = value; } };
spyOn(foo, 'setBar');
foo.setBar(123);
foo.setBar(456, 'baz');
});
it("has a rich set of tracking properties", function() {
expect(foo.setBar.calls.count()).toEqual(2); // tracks the number of calls
// tracks the args of each call
expect(foo.setBar.calls.argsFor(0)).toEqual([123]);
expect(foo.setBar.calls.argsFor(1)).toEqual([456, 'baz']);
// has shortcuts to the first and most recent call
expect(foo.setBar.calls.first().args).toEqual([123]);
expect(foo.setBar.calls.mostRecent().args).toEqual([456, 'baz']);
});
});
Spies — Other tracking properties (II)
describe("A spy", function() {
var foo, bar = null;
beforeEach(function() {
foo = { setBar: function(value) { bar = value; } };
spyOn(foo, 'setBar');
foo.setBar(123);
foo.setBar(456, 'baz');
});
it("has a rich set of tracking properties", function() {
// tracks the context and return values
expect(foo.setBar.calls.first().object).toEqual(foo);
expect(foo.setBar.calls.first().returnValue).toBeUndefined();
// can be reset
foo.setBar.calls.reset();
expect(foo.setBar.calls.count()).toBe(0);
});
});
Asynchronous support
describe("Asynchronous specs", function() {
var value;
beforeEach(function(done) {
setTimeout(function() {
value = 0;
done();
}, 100);
});
it("should support async execution of preparation and expectations", function(done) {
expect(value).toBe(0);
done();
});
});
Clock
describe("Manually ticking the Jasmine Clock", function() {
var timerCallback;
beforeEach(function() {
timerCallback = jasmine.createSpy();
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it("causes a timeout to be called synchronously", function() {
setTimeout(timerCallback, 100);
expect(timerCallback).not.toHaveBeenCalled();
jasmine.clock().tick(101);
expect(timerCallback).toHaveBeenCalled();
});
});
Clock — Mocking the date
describe("Mocking the Date object", function() {
beforeEach(function() {
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it("mocks the Date object and sets it to a given time", function() {
var baseTime = new Date(2013, 9, 23);
jasmine.clock().mockDate(baseTime);
jasmine.clock().tick(50);
expect(new Date().getTime()).toEqual(baseTime.getTime() + 50);
});
});
Sinon — Spies and Stubs
var spy = sinon.spy();
sinon.spy($, 'ajax');
$.ajax.restore();
sinon.stub($, 'ajax');
$.ajax.restore();
sinon.stub($, 'ajax', function(options) {
console.log(options.url);
});
$.ajax.restore();
Sinon — Fake timer
describe("Manually ticking the Clock", function() {
var clock, timerCallback;
beforeEach(function() {
timerCallback = sinon.spy();
clock = sinon.useFakeTimers();
});
afterEach(function() {
clock.restore();
});
it("causes a timeout to be called synchronously", function() {
setTimeout(timerCallback, 100);
expect(timerCallback.callCount).toBe(0);
clock.tick(101);
expect(timerCallback.callCount).toBe(1);
expect(new Date().getTime()).toBe(101);
});
});
Sinon — Fake server
describe("A suite with a sinon fakeServer", function() {
var server;
beforeEach(function() {
server = sinon.fakeServer.create();
server.autoRespond = true;
server.respondWith(function(xhr) {
xhr.respond(200, {'Content-Type':'application/json'}, JSON.stringify({'msg': 'msg'}));
});
server.xhr.useFilters = true;
server.xhr.addFilter(function(method, url) {
return !!url.match(/fixtures|css/); // If returns true the request will not be faked.
});
});
afterEach(function() {
server.restore();
});
});
More information in...
● https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScri
pt
● http://stackoverflow.com/questions/300855/javascript-unit-test-tools-
for-tdd
● http://jasmine.github.io/
● http://sinonjs.org/
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Workshop 5: JavaScript testing
Test Driven Development
“The best TDD can do is assure that the code does what the
programmer thinks it should do. That is pretty good by the way.”
— James Grenning
The cycle of TDD
Write a test
Run tests. Watch the new test fail
Make the test pass
Refactor to remove duplication
Benefits of TDD
Produces code that works
Honors the Single Responsibility Principle
Forces conscious development
Productivity boost
More information in...
● Test-Driven Development By Example, by Kent Beck.
Jasmine Disabling specs
xdescribe("A disabled suite", function() {
it("where the specs will not be executed", function() {
expect(2).toEqual(1);
});
});
describe("A suite", function() {
xit("with a disabled spec declared with 'xit'", function() {
expect(true).toBe(false);
});
it.only("with a spec that will be executed", function() {
expect(1).toBe(1);
});
it("with another spec that will not be executed", function() {
expect(1).toBe(1);
});
});
Asynchronous support
describe("long asynchronous specs", function() {
beforeEach(function(done) {
done();
}, 1000);
afterEach(function(done) {
done();
}, 1000);
it("takes a long time", function(done) {
setTimeout(done, 9000);
}, 10000);
});
Asynchronous support. Jasmine 1.3
describe("Asynchronous specs", function() {
var value, flag;
it("should support async execution of test preparation and expectations", function() {
flag = false;
value = 0;
setTimeout(function() {
flag = true;
}, 500);
waitsFor(function() {
value++;
return flag;
}, "The Value should be incremented", 750);
runs(function() {
expect(value).toBeGreaterThan(0);
});
});
});
jasmine.Clock v.1.3
it('description', function() {
jasmine.Clock.useMock();
setTimeout(function() {
console.log('print something');
}, 200);
jasmine.Clock.tick(190);
});
it('description', function() {
jasmine.Clock.useMock();
jasmine.Clock.tick(190);
});
Karma
npm install karma --save-dev
npm install karma-jasmine karma-chrome-launcher karma-phantomjs-launcher --save-dev
npm install karma-coverage --save-dev
npm install -g karma-cli
Installation
Configuration
karma init karma.conf.js npm install grunt-karma --save-dev
grunt.loadNpmTasks('grunt-karma');
karma: {
unit: {
configFile: 'karma.conf.js'
}
}
Grunt task
Karma configuration
The files array determines which files are included in the browser and which files are watched and
served by Karma.
Each pattern is either a simple string or an object with four properties:
pattern String, no default value. The pattern to use for matching. This property is mandatory.
watched Boolean (true). If autoWatch is true all files that have set watched to true will be watched
for changes.
included Boolean (true). Should the files be included in the browser using <script> tag? Use false if
you want to load them manually, eg. using Require.js.
served Boolean (true). Should the files be served by Karma's webserver?
THANKS FOR YOUR ATTENTION
Leave your questions on the comments section
Workshop 5: JavaScript testing

More Related Content

What's hot (20)

Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
Giovanni Scerra ☃
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascript
Doeun KOCH
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
kvangork
 
ES2015 workflows
ES2015 workflowsES2015 workflows
ES2015 workflows
Jarrod Overson
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
Leon van der Grient
 
Oojs 1.1
Oojs 1.1Oojs 1.1
Oojs 1.1
Rodica Dada
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8
Wilson Su
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
matuura_core
 
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8
Wilson Su
 
Unit testing with mocha
Unit testing with mochaUnit testing with mocha
Unit testing with mocha
Revath S Kumar
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
Chad Hietala
 
Javascript ES6 generators
Javascript ES6 generatorsJavascript ES6 generators
Javascript ES6 generators
RameshNair6
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
Dragos Ionita
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Java Script Best Practices
Java Script Best PracticesJava Script Best Practices
Java Script Best Practices
Enrique Juan de Dios
 
To Err Is Human
To Err Is HumanTo Err Is Human
To Err Is Human
Alex Liu
 
06 jQuery #burningkeyboards
06 jQuery  #burningkeyboards06 jQuery  #burningkeyboards
06 jQuery #burningkeyboards
Denis Ristic
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards
Denis Ristic
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
Eyal Vardi
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascript
Doeun KOCH
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
kvangork
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
Leon van der Grient
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8
Wilson Su
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
matuura_core
 
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8
Wilson Su
 
Unit testing with mocha
Unit testing with mochaUnit testing with mocha
Unit testing with mocha
Revath S Kumar
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
Chad Hietala
 
Javascript ES6 generators
Javascript ES6 generatorsJavascript ES6 generators
Javascript ES6 generators
RameshNair6
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
Dragos Ionita
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
To Err Is Human
To Err Is HumanTo Err Is Human
To Err Is Human
Alex Liu
 
06 jQuery #burningkeyboards
06 jQuery  #burningkeyboards06 jQuery  #burningkeyboards
06 jQuery #burningkeyboards
Denis Ristic
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards
Denis Ristic
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
Eyal Vardi
 

Viewers also liked (8)

Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
Visual Engineering
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
Visual Engineering
 
Workshop 15: Ionic framework
Workshop 15: Ionic frameworkWorkshop 15: Ionic framework
Workshop 15: Ionic framework
Visual Engineering
 
Workshop 9: BackboneJS y patrones MVC
Workshop 9: BackboneJS y patrones MVCWorkshop 9: BackboneJS y patrones MVC
Workshop 9: BackboneJS y patrones MVC
Visual Engineering
 
Workshop 7: Single Page Applications
Workshop 7: Single Page ApplicationsWorkshop 7: Single Page Applications
Workshop 7: Single Page Applications
Visual Engineering
 
Legal protection in public procurement, Zoran Blazevic, SIGMA regional confer...
Legal protection in public procurement, Zoran Blazevic, SIGMA regional confer...Legal protection in public procurement, Zoran Blazevic, SIGMA regional confer...
Legal protection in public procurement, Zoran Blazevic, SIGMA regional confer...
Support for Improvement in Governance and Management SIGMA
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
Visual Engineering
 
Ad

Similar to Workshop 5: JavaScript testing (20)

Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
Ynon Perek
 
Introduccion a Jasmin
Introduccion a JasminIntroduccion a Jasmin
Introduccion a Jasmin
Rodrigo Quelca Sirpa
 
AngularJS Testing
AngularJS TestingAngularJS Testing
AngularJS Testing
Eyal Vardi
 
Jasmine BDD for Javascript
Jasmine BDD for JavascriptJasmine BDD for Javascript
Jasmine BDD for Javascript
Luis Alfredo Porras Páez
 
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
 
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
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
GlobalLogic Ukraine
 
Unit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and NodeUnit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and Node
Josh Mock
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and Karma
Christopher Bartling
 
Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)
Anna Khabibullina
 
JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014
DA-14
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
Roy Yu
 
Test-Driven JavaScript Development (JavaZone 2010)
Test-Driven JavaScript Development (JavaZone 2010)Test-Driven JavaScript Development (JavaZone 2010)
Test-Driven JavaScript Development (JavaZone 2010)
Christian Johansen
 
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
 
An Introduction to the World of Testing for Front-End Developers
An Introduction to the World of Testing for Front-End DevelopersAn Introduction to the World of Testing for Front-End Developers
An Introduction to the World of Testing for Front-End Developers
FITC
 
FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...
FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...
FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...
Haris Mahmood
 
In search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingIn search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testing
Anna Khabibullina
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
jeresig
 
Java Script Isn\'t a Toy Anymore
Java Script Isn\'t a Toy AnymoreJava Script Isn\'t a Toy Anymore
Java Script Isn\'t a Toy Anymore
Alexis Williams
 
Backbone testing
Backbone testingBackbone testing
Backbone testing
Crashlytics
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
Ynon Perek
 
AngularJS Testing
AngularJS TestingAngularJS Testing
AngularJS Testing
Eyal Vardi
 
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
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
Christopher Bartling
 
Unit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and NodeUnit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and Node
Josh Mock
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and Karma
Christopher Bartling
 
Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)
Anna Khabibullina
 
JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014
DA-14
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
Roy Yu
 
Test-Driven JavaScript Development (JavaZone 2010)
Test-Driven JavaScript Development (JavaZone 2010)Test-Driven JavaScript Development (JavaZone 2010)
Test-Driven JavaScript Development (JavaZone 2010)
Christian Johansen
 
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
 
An Introduction to the World of Testing for Front-End Developers
An Introduction to the World of Testing for Front-End DevelopersAn Introduction to the World of Testing for Front-End Developers
An Introduction to the World of Testing for Front-End Developers
FITC
 
FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...
FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...
FITC Web Unleashed 2017 - Introduction to the World of Testing for Front-End ...
Haris Mahmood
 
In search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testingIn search of JavaScript code quality: unit testing
In search of JavaScript code quality: unit testing
Anna Khabibullina
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
jeresig
 
Java Script Isn\'t a Toy Anymore
Java Script Isn\'t a Toy AnymoreJava Script Isn\'t a Toy Anymore
Java Script Isn\'t a Toy Anymore
Alexis Williams
 
Backbone testing
Backbone testingBackbone testing
Backbone testing
Crashlytics
 
Ad

More from Visual Engineering (20)

Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJS
Visual Engineering
 
Workshop iOS 4: Closures, generics & operators
Workshop iOS 4: Closures, generics & operatorsWorkshop iOS 4: Closures, generics & operators
Workshop iOS 4: Closures, generics & operators
Visual Engineering
 
Workshop iOS 3: Testing, protocolos y extensiones
Workshop iOS 3: Testing, protocolos y extensionesWorkshop iOS 3: Testing, protocolos y extensiones
Workshop iOS 3: Testing, protocolos y extensiones
Visual Engineering
 
Workshop iOS 2: Swift - Structures
Workshop iOS 2: Swift - StructuresWorkshop iOS 2: Swift - Structures
Workshop iOS 2: Swift - Structures
Visual Engineering
 
Workhop iOS 1: Fundamentos de Swift
Workhop iOS 1: Fundamentos de SwiftWorkhop iOS 1: Fundamentos de Swift
Workhop iOS 1: Fundamentos de Swift
Visual Engineering
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
Visual Engineering
 
Workshop 24: React Native Introduction
Workshop 24: React Native IntroductionWorkshop 24: React Native Introduction
Workshop 24: React Native Introduction
Visual Engineering
 
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
 
Workshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux AdvancedWorkshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux Advanced
Visual Engineering
 
Workshop 22: React-Redux Middleware
Workshop 22: React-Redux MiddlewareWorkshop 22: React-Redux Middleware
Workshop 22: React-Redux Middleware
Visual Engineering
 
Workshop 21: React Router
Workshop 21: React RouterWorkshop 21: React Router
Workshop 21: React Router
Visual Engineering
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxWorkshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & Redux
Visual Engineering
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
Visual Engineering
 
Workshop 18: CSS Animations & cool effects
Workshop 18: CSS Animations & cool effectsWorkshop 18: CSS Animations & cool effects
Workshop 18: CSS Animations & cool effects
Visual Engineering
 
Workshop 17: EmberJS parte II
Workshop 17: EmberJS parte IIWorkshop 17: EmberJS parte II
Workshop 17: EmberJS parte II
Visual Engineering
 
Workshop 16: EmberJS Parte I
Workshop 16: EmberJS Parte IWorkshop 16: EmberJS Parte I
Workshop 16: EmberJS Parte I
Visual Engineering
 
Workshop 11: Trendy web designs & prototyping
Workshop 11: Trendy web designs & prototypingWorkshop 11: Trendy web designs & prototyping
Workshop 11: Trendy web designs & prototyping
Visual Engineering
 
Workshop 6: Designer tools
Workshop 6: Designer toolsWorkshop 6: Designer tools
Workshop 6: Designer tools
Visual Engineering
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
Visual Engineering
 
Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJS
Visual Engineering
 
Workshop iOS 4: Closures, generics & operators
Workshop iOS 4: Closures, generics & operatorsWorkshop iOS 4: Closures, generics & operators
Workshop iOS 4: Closures, generics & operators
Visual Engineering
 
Workshop iOS 3: Testing, protocolos y extensiones
Workshop iOS 3: Testing, protocolos y extensionesWorkshop iOS 3: Testing, protocolos y extensiones
Workshop iOS 3: Testing, protocolos y extensiones
Visual Engineering
 
Workshop iOS 2: Swift - Structures
Workshop iOS 2: Swift - StructuresWorkshop iOS 2: Swift - Structures
Workshop iOS 2: Swift - Structures
Visual Engineering
 
Workhop iOS 1: Fundamentos de Swift
Workhop iOS 1: Fundamentos de SwiftWorkhop iOS 1: Fundamentos de Swift
Workhop iOS 1: Fundamentos de Swift
Visual Engineering
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
Visual Engineering
 
Workshop 24: React Native Introduction
Workshop 24: React Native IntroductionWorkshop 24: React Native Introduction
Workshop 24: React Native Introduction
Visual Engineering
 
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
 
Workshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux AdvancedWorkshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux Advanced
Visual Engineering
 
Workshop 22: React-Redux Middleware
Workshop 22: React-Redux MiddlewareWorkshop 22: React-Redux Middleware
Workshop 22: React-Redux Middleware
Visual Engineering
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxWorkshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & Redux
Visual Engineering
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
Visual Engineering
 
Workshop 18: CSS Animations & cool effects
Workshop 18: CSS Animations & cool effectsWorkshop 18: CSS Animations & cool effects
Workshop 18: CSS Animations & cool effects
Visual Engineering
 
Workshop 11: Trendy web designs & prototyping
Workshop 11: Trendy web designs & prototypingWorkshop 11: Trendy web designs & prototyping
Workshop 11: Trendy web designs & prototyping
Visual Engineering
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
Visual Engineering
 

Recently uploaded (20)

Migrating to Azure Cosmos DB the Right Way
Migrating to Azure Cosmos DB the Right WayMigrating to Azure Cosmos DB the Right Way
Migrating to Azure Cosmos DB the Right Way
Alexander (Alex) Komyagin
 
wAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptxwAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptx
SimonedeGijt
 
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
 
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free DownloadWondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Puppy jhon
 
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
 
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
 
Bonk coin airdrop_ Everything You Need to Know.pdf
Bonk coin airdrop_ Everything You Need to Know.pdfBonk coin airdrop_ Everything You Need to Know.pdf
Bonk coin airdrop_ Everything You Need to Know.pdf
Herond Labs
 
Marketo & Dynamics can be Most Excellent to Each Other – The Sequel
Marketo & Dynamics can be Most Excellent to Each Other – The SequelMarketo & Dynamics can be Most Excellent to Each Other – The Sequel
Marketo & Dynamics can be Most Excellent to Each Other – The Sequel
BradBedford3
 
Artificial Intelligence Applications Across Industries
Artificial Intelligence Applications Across IndustriesArtificial Intelligence Applications Across Industries
Artificial Intelligence Applications Across Industries
SandeepKS52
 
Top 5 Task Management Software to Boost Productivity in 2025
Top 5 Task Management Software to Boost Productivity in 2025Top 5 Task Management Software to Boost Productivity in 2025
Top 5 Task Management Software to Boost Productivity in 2025
Orangescrum
 
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptxIMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
usmanch7829
 
Porting Qt 5 QML Modules to Qt 6 Webinar
Porting Qt 5 QML Modules to Qt 6 WebinarPorting Qt 5 QML Modules to Qt 6 Webinar
Porting Qt 5 QML Modules to Qt 6 Webinar
ICS
 
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
 
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlowDevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
Aarno Aukia
 
OpenTelemetry 101 Cloud Native Barcelona
OpenTelemetry 101 Cloud Native BarcelonaOpenTelemetry 101 Cloud Native Barcelona
OpenTelemetry 101 Cloud Native Barcelona
Imma Valls Bernaus
 
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
 
Generative Artificial Intelligence and its Applications
Generative Artificial Intelligence and its ApplicationsGenerative Artificial Intelligence and its Applications
Generative Artificial Intelligence and its Applications
SandeepKS52
 
Agentic Techniques in Retrieval-Augmented Generation with Azure AI Search
Agentic Techniques in Retrieval-Augmented Generation with Azure AI SearchAgentic Techniques in Retrieval-Augmented Generation with Azure AI Search
Agentic Techniques in Retrieval-Augmented Generation with Azure AI Search
Maxim Salnikov
 
The Future of Open Source Reporting Best Alternatives to Jaspersoft.pdf
The Future of Open Source Reporting Best Alternatives to Jaspersoft.pdfThe Future of Open Source Reporting Best Alternatives to Jaspersoft.pdf
The Future of Open Source Reporting Best Alternatives to Jaspersoft.pdf
Varsha Nayak
 
Key AI Technologies Used by Indian Artificial Intelligence Companies
Key AI Technologies Used by Indian Artificial Intelligence CompaniesKey AI Technologies Used by Indian Artificial Intelligence Companies
Key AI Technologies Used by Indian Artificial Intelligence Companies
Mypcot Infotech
 
wAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptxwAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptx
SimonedeGijt
 
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
 
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free DownloadWondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Puppy jhon
 
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
 
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
 
Bonk coin airdrop_ Everything You Need to Know.pdf
Bonk coin airdrop_ Everything You Need to Know.pdfBonk coin airdrop_ Everything You Need to Know.pdf
Bonk coin airdrop_ Everything You Need to Know.pdf
Herond Labs
 
Marketo & Dynamics can be Most Excellent to Each Other – The Sequel
Marketo & Dynamics can be Most Excellent to Each Other – The SequelMarketo & Dynamics can be Most Excellent to Each Other – The Sequel
Marketo & Dynamics can be Most Excellent to Each Other – The Sequel
BradBedford3
 
Artificial Intelligence Applications Across Industries
Artificial Intelligence Applications Across IndustriesArtificial Intelligence Applications Across Industries
Artificial Intelligence Applications Across Industries
SandeepKS52
 
Top 5 Task Management Software to Boost Productivity in 2025
Top 5 Task Management Software to Boost Productivity in 2025Top 5 Task Management Software to Boost Productivity in 2025
Top 5 Task Management Software to Boost Productivity in 2025
Orangescrum
 
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptxIMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
usmanch7829
 
Porting Qt 5 QML Modules to Qt 6 Webinar
Porting Qt 5 QML Modules to Qt 6 WebinarPorting Qt 5 QML Modules to Qt 6 Webinar
Porting Qt 5 QML Modules to Qt 6 Webinar
ICS
 
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
 
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlowDevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
Aarno Aukia
 
OpenTelemetry 101 Cloud Native Barcelona
OpenTelemetry 101 Cloud Native BarcelonaOpenTelemetry 101 Cloud Native Barcelona
OpenTelemetry 101 Cloud Native Barcelona
Imma Valls Bernaus
 
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
 
Generative Artificial Intelligence and its Applications
Generative Artificial Intelligence and its ApplicationsGenerative Artificial Intelligence and its Applications
Generative Artificial Intelligence and its Applications
SandeepKS52
 
Agentic Techniques in Retrieval-Augmented Generation with Azure AI Search
Agentic Techniques in Retrieval-Augmented Generation with Azure AI SearchAgentic Techniques in Retrieval-Augmented Generation with Azure AI Search
Agentic Techniques in Retrieval-Augmented Generation with Azure AI Search
Maxim Salnikov
 
The Future of Open Source Reporting Best Alternatives to Jaspersoft.pdf
The Future of Open Source Reporting Best Alternatives to Jaspersoft.pdfThe Future of Open Source Reporting Best Alternatives to Jaspersoft.pdf
The Future of Open Source Reporting Best Alternatives to Jaspersoft.pdf
Varsha Nayak
 
Key AI Technologies Used by Indian Artificial Intelligence Companies
Key AI Technologies Used by Indian Artificial Intelligence CompaniesKey AI Technologies Used by Indian Artificial Intelligence Companies
Key AI Technologies Used by Indian Artificial Intelligence Companies
Mypcot Infotech
 

Workshop 5: JavaScript testing

  • 1. Front End Workshops VI.JavaScript testing. Client vs. Server testing. Test Driven Development Raúl Delgado Astudillo [email protected] Mario García Martín [email protected]
  • 2. JavaScript testing “Testing is an infinite process of comparing the invisible to the ambiguous in order to avoid the unthinkable happening to the anonymous.” — James Bach
  • 3. What is a test? Type some code Open and load the browser Prove functionality A test is (simply) the validation of an expectation. Manual testing... ...is NOT enough!
  • 4. Can we do better? Manual testing is... Time consuming Error prone Irreproducible (Nearly) Impossible if we want to test a wide set of browsers and platforms YES!! Automated testing
  • 5. Tests should be Fast to run Easy to understand Isolated Not reliant on an Internet connection
  • 6. Benefits and pitfalls of testing Regression testing Refactoring Cross-browser testing Good documentation Helps us write cleaner interfaces (testable code) Writing good tests can be challenging
  • 7. More information in... ● Test-Driven JavaScript Development, by Christian Johansen ● https://en.wikipedia.org/wiki/Software_testing
  • 8. Client testing “A passing test doesn't mean no problem. It means no problem observed. This time. With these inputs. So far. On my machine.” — Michael Bolton
  • 10. Jasmine — Scaffolding describe("A suite with setup and tear-down", function() { var foo; beforeAll(function() {}); afterAll(function() {}); beforeEach(function() { foo = 1; }); afterEach(function() { foo = 0; }); it("can contain specs with one or more expectations", function() { expect(foo).toBe(1); expect(true).toBe(true); }); });
  • 11. Matchers expect(3).toBe(3); // Compares with === expect({a: 3}).toEqual({a: 3}); // For comparison of objects expect('barely').toMatch(/bar/); // For regular expressions expect(null).toBeDefined(); // Compares against undefined expect(undefined).toBeUndefined(); // Compares against undefined expect(null).toBeNull(); // Compares against null expect('hello').toBeTruthy(); // For boolean casting testing expect('').toBeFalsy(); // For boolean casting testing expect(['bar', 'foo']).toContain('bar'); // For finding an item in an Array expect(2).toBeLessThan(3); // For mathematical comparisons expect(3).toBeGreaterThan(2); // For mathematical comparisons expect(3.14).toBeCloseTo(3.17, 1); // For precision math comparison // For testing if a function throws an exception expect(function() { throw new Error('Error!'); }).toThrow(); // Modifier 'not' expect(false).not.toBe(true);
  • 12. Spies describe("A suite", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar'); foo.setBar(123); foo.setBar(456, 'another param'); }); it("that defines a spy out of the box", function() { expect(foo.setBar).toHaveBeenCalled(); // tracks that the spy was called // tracks all the arguments of its calls expect(foo.setBar).toHaveBeenCalledWith(123); expect(foo.setBar).toHaveBeenCalledWith(456, 'another param'); expect(bar).toBeNull(); // stops all execution on a function }); });
  • 13. Spies — and.callthrough describe("A suite", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar').and.callThrough(); foo.setBar(123); }); it("that defines a spy configured to call through", function() { expect(foo.setBar).toHaveBeenCalled(); // tracks that the spy was called expect(bar).toEqual(123); // the spied function has been called }); });
  • 14. describe("A suite", function() { var foo, bar = null; beforeEach(function() { foo = { getBar: function() { return bar; } }; spyOn(foo, 'getBar').and.returnValue(745); }); it("that defines a spy configured to fake a return value", function() { expect(foo.getBar()).toBe(745); // when called returns the requested value expect(bar).toBeNull(); // should not affect the variable }); }); Spies — and.returnValue
  • 15. describe("A suite", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar').and.callFake(function() { console.log('hello'); }); foo.setBar(); // logs hello in the console. }); it("that defines a spy configured with an alternate implementation", function() { expect(foo.setBar).toHaveBeenCalled(); // tracks that the spy was called expect(bar).toBeNull(); // should not affect the variable }); }); Spies — and.callFake
  • 16. Spies — createSpy describe("A suite", function() { var spy; beforeAll(function() { $(window).on('resize', function() { $(window).trigger('myEvent'); }); }); afterAll(function() { $(window).off('resize'); }); beforeEach(function() { spy = jasmine.createSpy(); }); it("that defines a spy created manually", function() { $(window).on('myEvent', spy); $(window).trigger('resize'); expect(spy).toHaveBeenCalled(); // tracks that the spy was called }); });
  • 17. Spies — Other tracking properties (I) describe("A spy", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar'); foo.setBar(123); foo.setBar(456, 'baz'); }); it("has a rich set of tracking properties", function() { expect(foo.setBar.calls.count()).toEqual(2); // tracks the number of calls // tracks the args of each call expect(foo.setBar.calls.argsFor(0)).toEqual([123]); expect(foo.setBar.calls.argsFor(1)).toEqual([456, 'baz']); // has shortcuts to the first and most recent call expect(foo.setBar.calls.first().args).toEqual([123]); expect(foo.setBar.calls.mostRecent().args).toEqual([456, 'baz']); }); });
  • 18. Spies — Other tracking properties (II) describe("A spy", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar'); foo.setBar(123); foo.setBar(456, 'baz'); }); it("has a rich set of tracking properties", function() { // tracks the context and return values expect(foo.setBar.calls.first().object).toEqual(foo); expect(foo.setBar.calls.first().returnValue).toBeUndefined(); // can be reset foo.setBar.calls.reset(); expect(foo.setBar.calls.count()).toBe(0); }); });
  • 19. Asynchronous support describe("Asynchronous specs", function() { var value; beforeEach(function(done) { setTimeout(function() { value = 0; done(); }, 100); }); it("should support async execution of preparation and expectations", function(done) { expect(value).toBe(0); done(); }); });
  • 20. Clock describe("Manually ticking the Jasmine Clock", function() { var timerCallback; beforeEach(function() { timerCallback = jasmine.createSpy(); jasmine.clock().install(); }); afterEach(function() { jasmine.clock().uninstall(); }); it("causes a timeout to be called synchronously", function() { setTimeout(timerCallback, 100); expect(timerCallback).not.toHaveBeenCalled(); jasmine.clock().tick(101); expect(timerCallback).toHaveBeenCalled(); }); });
  • 21. Clock — Mocking the date describe("Mocking the Date object", function() { beforeEach(function() { jasmine.clock().install(); }); afterEach(function() { jasmine.clock().uninstall(); }); it("mocks the Date object and sets it to a given time", function() { var baseTime = new Date(2013, 9, 23); jasmine.clock().mockDate(baseTime); jasmine.clock().tick(50); expect(new Date().getTime()).toEqual(baseTime.getTime() + 50); }); });
  • 22. Sinon — Spies and Stubs var spy = sinon.spy(); sinon.spy($, 'ajax'); $.ajax.restore(); sinon.stub($, 'ajax'); $.ajax.restore(); sinon.stub($, 'ajax', function(options) { console.log(options.url); }); $.ajax.restore();
  • 23. Sinon — Fake timer describe("Manually ticking the Clock", function() { var clock, timerCallback; beforeEach(function() { timerCallback = sinon.spy(); clock = sinon.useFakeTimers(); }); afterEach(function() { clock.restore(); }); it("causes a timeout to be called synchronously", function() { setTimeout(timerCallback, 100); expect(timerCallback.callCount).toBe(0); clock.tick(101); expect(timerCallback.callCount).toBe(1); expect(new Date().getTime()).toBe(101); }); });
  • 24. Sinon — Fake server describe("A suite with a sinon fakeServer", function() { var server; beforeEach(function() { server = sinon.fakeServer.create(); server.autoRespond = true; server.respondWith(function(xhr) { xhr.respond(200, {'Content-Type':'application/json'}, JSON.stringify({'msg': 'msg'})); }); server.xhr.useFilters = true; server.xhr.addFilter(function(method, url) { return !!url.match(/fixtures|css/); // If returns true the request will not be faked. }); }); afterEach(function() { server.restore(); }); });
  • 25. More information in... ● https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScri pt ● http://stackoverflow.com/questions/300855/javascript-unit-test-tools- for-tdd ● http://jasmine.github.io/ ● http://sinonjs.org/
  • 37. Test Driven Development “The best TDD can do is assure that the code does what the programmer thinks it should do. That is pretty good by the way.” — James Grenning
  • 38. The cycle of TDD Write a test Run tests. Watch the new test fail Make the test pass Refactor to remove duplication
  • 39. Benefits of TDD Produces code that works Honors the Single Responsibility Principle Forces conscious development Productivity boost
  • 40. More information in... ● Test-Driven Development By Example, by Kent Beck.
  • 41. Jasmine Disabling specs xdescribe("A disabled suite", function() { it("where the specs will not be executed", function() { expect(2).toEqual(1); }); }); describe("A suite", function() { xit("with a disabled spec declared with 'xit'", function() { expect(true).toBe(false); }); it.only("with a spec that will be executed", function() { expect(1).toBe(1); }); it("with another spec that will not be executed", function() { expect(1).toBe(1); }); });
  • 42. Asynchronous support describe("long asynchronous specs", function() { beforeEach(function(done) { done(); }, 1000); afterEach(function(done) { done(); }, 1000); it("takes a long time", function(done) { setTimeout(done, 9000); }, 10000); });
  • 43. Asynchronous support. Jasmine 1.3 describe("Asynchronous specs", function() { var value, flag; it("should support async execution of test preparation and expectations", function() { flag = false; value = 0; setTimeout(function() { flag = true; }, 500); waitsFor(function() { value++; return flag; }, "The Value should be incremented", 750); runs(function() { expect(value).toBeGreaterThan(0); }); }); });
  • 44. jasmine.Clock v.1.3 it('description', function() { jasmine.Clock.useMock(); setTimeout(function() { console.log('print something'); }, 200); jasmine.Clock.tick(190); }); it('description', function() { jasmine.Clock.useMock(); jasmine.Clock.tick(190); });
  • 45. Karma npm install karma --save-dev npm install karma-jasmine karma-chrome-launcher karma-phantomjs-launcher --save-dev npm install karma-coverage --save-dev npm install -g karma-cli Installation Configuration karma init karma.conf.js npm install grunt-karma --save-dev grunt.loadNpmTasks('grunt-karma'); karma: { unit: { configFile: 'karma.conf.js' } } Grunt task
  • 46. Karma configuration The files array determines which files are included in the browser and which files are watched and served by Karma. Each pattern is either a simple string or an object with four properties: pattern String, no default value. The pattern to use for matching. This property is mandatory. watched Boolean (true). If autoWatch is true all files that have set watched to true will be watched for changes. included Boolean (true). Should the files be included in the browser using <script> tag? Use false if you want to load them manually, eg. using Require.js. served Boolean (true). Should the files be served by Karma's webserver?
  • 47. THANKS FOR YOUR ATTENTION Leave your questions on the comments section