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


Top Related