unit testing front-end javascript

25
UNIT TESTING FRONT END JAVASCRIPT YURI TAKHTEYEV @QARAMAZOV @RANGLEIO

Upload: rangleio

Post on 01-Jul-2015

345 views

Category:

Technology


4 download

DESCRIPTION

Building complex software application can be made much easier with unit testing – a fact well established in back-end work but often overlooked on the front-end. Yuri Takhteyev will look at some of the tools and techniques for unit testing front end code, focusing on Mocha and Karma. Most of the examples will draw on AngularJS but the main ideas are applicable to other frameworks as well.

TRANSCRIPT

Page 1: Unit Testing Front-End JavaScript

UNIT TESTING FRONT END JAVASCRIPT

YURI TAKHTEYEV

@QARAMAZOV@RANGLEIO

Page 2: Unit Testing Front-End JavaScript

Why Bother with Unit Tests?

Page 3: Unit Testing Front-End JavaScript

Why Bother with Unit Tests?

Page 4: Unit Testing Front-End JavaScript

TDD Lite

Page 5: Unit Testing Front-End JavaScript

Writing Testable Code

☛ Modular code

☛ AngularJS

services

☛ Other modules not entangled with DOM

Page 6: Unit Testing Front-End JavaScript

Keeping Tests Simple

Page 7: Unit Testing Front-End JavaScript

Common Tools

Runner: KarmaTask Automation: Gulp || GruntScorer: Mocha || JasmineAssertions: Chai || JasmineSpies: Sinon || Jasmin

+ CI tools (e.g. Magnum-CI)

Page 8: Unit Testing Front-End JavaScript

http://yto.io/xunit

Page 9: Unit Testing Front-End JavaScript

Installing the Example Code

# First installgit clone https://github.com/yuri/webu-unit.gitcd webu-unitnpm installsudo npm install -g gulpsudo npm install -g bowerbower install

# Now rungulp karma

☛ You’ll need to install git and node before

Page 10: Unit Testing Front-End JavaScript

A Basic Testfunction isOdd(value) { return (value % 2 === 1);}

describe('isEven', function () { it('should handle positive ints', function () { if (isOdd(2)) { throw new Error('2 should be even'); } });});

☛ Let’s put this in “client/app/is-odd.test.js”

Page 11: Unit Testing Front-End JavaScript

Chaidescribe('isEven', function () { it('should handle positive ints', function () { expect(isOdd(1)).to.be.true; expect(isOdd(2)).to.be.false; expect(isOdd(3)).to.be.true; });});

☛ More Chai at http://chaijs.com/api/bdd/

Page 12: Unit Testing Front-End JavaScript

Extending Testsdescribe('isEven', function () { ... it('should handle negative ints', function () { expect(isOdd(-1)).to.be.true; });});

Page 13: Unit Testing Front-End JavaScript

Extending Testsdescribe('isEven', function () { ... xit('should handle negative ints', function () { expect(isOdd(-1)).to.be.true; });});

Page 14: Unit Testing Front-End JavaScript

Extending Testsdescribe('isEven', function () { ... it.only('should handle negative ints', function () { expect(isOdd(-1)).to.be.true; });});

Page 15: Unit Testing Front-End JavaScript

Extending Testsdescribe('isEven', function () { ... it('should handle negative ints', function () { expect(isOdd(-1)).to.be.true; });});

function isOdd(value) { return (value % 2 === 1);}

Page 16: Unit Testing Front-End JavaScript

Testing a Serviceangular.module('app.tasks', [ 'app.server'])

.factory('tasks', function(server) { var service = {};

service.getTasks = function () { return server.get('tasks'); };

return service;});

☛ Let’s put this in “client/app/tasks-service.js”

Page 17: Unit Testing Front-End JavaScript

The Test, Take 1describe('tasks service', function () { beforeEach(module('app.tasks')); it('should get tasks', function() { var tasks = getService('tasks'); expect(tasks.getTasks()).to .not.be.undefined; });});

☛ Let’s put this in “client/app/tasks-service.test.js”

Error: [$injector:unpr] Unknown provider:serverProvider <- server <- tasks

☛ See “client/testing/test-utils.js” for implementation of getService().

Page 18: Unit Testing Front-End JavaScript

Mocking Dependenciesvar data;beforeEach(module(function($provide){ $provide.service('server', function() { return { get: function() { return Q.when(data); } }; }); $provide.service('$q', function() { return Q; });}));

Chrome 37.0.2062 (Mac OS X 10.9.4): Executed 3 of 3 SUCCESS (0.046 secs / 0.027 secs)

Page 19: Unit Testing Front-End JavaScript

Let’s Extend the Serviceservice.getMyTasks = function () { return server.getTasks() .then(function(taskArray) { return _.filter(taskArray, function(task) { return task.owner === user.userName; }); });};

☛ We’ll need to inject “user” into the service

Page 20: Unit Testing Front-End JavaScript

Mocking the User$provide.service('user', function() { return { username: 'yuri' };});

☛ The mock can be very simple

Page 21: Unit Testing Front-End JavaScript

An Async Test, Wrongit('should get user\'s tasks', function() { var tasks = getService('tasks'); data = [{ owner: 'bob', description: 'Mow the lawn' }, { owner: 'yuri', description: 'Save the world' }]; tasks.getMyTasks() .then(function(myTasks) { expect(myTasks.length).to.equal(1); });});

☛ Always check that “wrong” tests fail!

Page 22: Unit Testing Front-End JavaScript

An Async Test, Rightit('should get user\'s tasks', function() { var tasks = getService('tasks'); data = [{ owner: 'bob', description: 'Mow the lawn' }, { owner: 'yuri', description: 'Save the world' }]; return tasks.getMyTasks() .then(function(myTasks) { expect(myTasks.length).to.equal(1); });});

Page 23: Unit Testing Front-End JavaScript

Spies with Sinon$provide.service('server', function() { return { get: sinon.spy(function() { return Q.when(data); }) };});

var server = getService('server');return tasks.getMyTasks() .then(function(myTasks) { expect(myTasks.length).to.equal(1); server.get.should.have.been.calledOnce; });

Page 24: Unit Testing Front-End JavaScript

Thank You.Contact: [email protected] http://yto.io @qaramazov

This presentation: http://yto.io/xunit