full stack unit testing

41
Full-stack unit- testing Tech talk @ Pause

Upload: globallogic-ukraine

Post on 12-Jul-2015

1.061 views

Category:

Engineering


7 download

TRANSCRIPT

Page 1: Full Stack Unit Testing

Full-stack unit-

testingTech talk @ Pause

Page 2: Full Stack Unit Testing

Plan1. Overview of frameworks and libraries for testing

2. Testing of client side web application

a. Test runner

b. Unit testing stack

c. End-2-end testing

d. Reporting

e. Sample: angular application testing

3. Testing of server side

a. Mocking of data providers

b. Fixtures

c. Essentials of tests

4. Pitfalls of unit testing

Page 3: Full Stack Unit Testing

Overview of frameworks

Page 4: Full Stack Unit Testing

Testing of client-side

1. Test runner - runs unit tests suite in various

browsers and write reports using different

formats

2. Frameworks - skeleton for unit tests suites

3. Utils libraries - allow to write tests in more

expressive

Page 5: Full Stack Unit Testing

Test runner

1. Dynamically generate index file using

required libs, sources and tests

2. Execute web server on background

3. Run tests in different browsers

4. Collect test results from expectations and

asserts

5. Format them into report

Page 6: Full Stack Unit Testing

Test runner

Test’em - simple test

runner1. Framework config:

Mocha, Jasmine

2. Test files

3. Serve files

4. Browser stack config

Page 7: Full Stack Unit Testing

Test runner

Karma - advanced test

runner1. Plugins

2. Multiple report formats

supported

3. Various browsers

4. Dynamic index.html

generation

Page 8: Full Stack Unit Testing

Test runner

Essentials

1. Synchronization between source files

2. Integration of frameworks

3. Debugging

Page 9: Full Stack Unit Testing

Unit testing stack

Testing framework

API● TDD

● BDD

Main frameworks● Mocha

● Jasmine

● describeo skip

o only

● it

● before(done)

● after(done)

● beforeEach

● afterEach

Page 10: Full Stack Unit Testing

Unit testing stack

Assertion libraries

Chai● Plugins

● Supports should and

expect style

Should

● expect(foo).to.deep.

equal(someNested

Array)

● should.exist(foo)

● foo.bar.should.have

.property(‘bar’)

Page 11: Full Stack Unit Testing

Unit testing stack

Plugins for chai

● Allows you to write

tests in terms of

libraries you are

using

● Syntactic sugar

● Sinon.js

● jQuery

● Backbone

● Q

Page 12: Full Stack Unit Testing

Unit testing stack

Page 13: Full Stack Unit Testing

End-2-end testing

Protractor (previously

angular-scenario):

● Access to angular

scope from view

● Selectors for

directives

● Uses selenium

● by.o id

o css

o model

o binding

● elemento sendKeys

o setPosition

o setSize

Page 14: Full Stack Unit Testing

End-2-end testing

Page 15: Full Stack Unit Testing

Reporting

● jUnit XML - Jenkins

love it

● Progress, Dots - for

console lovers

● Coverage -

objective metrics

● jUnit is has better

support of Jasmine

● Coverage settings -

include all sources

not tests

Page 16: Full Stack Unit Testing

Reporting

Page 17: Full Stack Unit Testing
Page 18: Full Stack Unit Testing

Sample angular app testingbeforeEach(inject(function ($controller, $rootScope) {

scope = $rootScope.$new();

GamesCtrl = $controller('HotelsCtrl', {

$scope: scope, Hotels: factory

});

}));

it('should set default value for orderProp', function () {

expect(scope.orderProp).toBe('title');

});

it('should have a List of Hotels', function () {

expect(scope.games.length).toBe(2);

expect(scope.games[0].title).toBe('Hilton');

expect(scope.games[1].freeRooms).toBe(10);

});

Page 19: Full Stack Unit Testing

Testing of server side

Page 20: Full Stack Unit Testing

Mocking of data providers

Faker.js

● id’s

● names, emails

● cities, locations

● messages, sentences, paragraphs

Sinon.js

● Mocking API using sinon.mock(API)

Page 21: Full Stack Unit Testing

Sample code//Hotels data

'use strict';

var Faker = require('Faker');

function generateOne() {

return {

name: Faker.random.bk_noun(),

address: Faker.Addresses.streetAddress(),

capacity: {

standard: Faker.helpers.randomNumber(100),

economy: Faker.helpers.randomNumber(100),

luxury: Faker.helpers.randomNumber(100)

}

};

}

module.exports.generateOne = generateOne;

module.exports.generateMany = function (count) {

var result = [];

for (var i = 0; i < count; i++) {

result.push(generateOne())

}

return result;

}

Page 22: Full Stack Unit Testing

Database mapping testing

1. No need to test mongoose API

2. Create stub data using Faker API and

predefined JSON

3. Insert it into DB inside before callback

4. Run unit test suites on test data

5. Remove data from DB inside after callback

Page 23: Full Stack Unit Testing

Sample codevar fixtures = require('fixtures.js');

var api = require('api/');

var expect = require('chai').expect;

var COUNT = 100;

describe('Booking API', function () {

describe('#search', function () {

before(function (done) {

fixtures.prepareData('hotels',

COUNT, done);

});

it('should return all hotes if no query

params provided', function (done)

{api.search('hotels', function (err,

data) {

expect(err).to.be.null;

expect(data).to.be.an('object');

expect(data.length).to.be.eql(COUNT);

done();

….

after(function (done) {

fixtures.destroyData('hotels');

Page 24: Full Stack Unit Testing

Alternatives

● https://github.com/petejkim/factory-lady

● http://chaijs.com/plugins/chai-factories

● https://www.npmjs.com/package/rosie

Page 25: Full Stack Unit Testing

Fixtures

Rules

1. Do not hardcode the id’s and data that is

generated by database

2. Put all domain specific data into fixtures,

group them by collections

3. Do not put null to client API object. Use

dummy object instead.

Page 26: Full Stack Unit Testing

Sample code// Fixtures

var async = require('async');

var hotelsData = require('./hotelsData');

var Hotel = require('./hotelModel');

module.exports.prepareData = function (name, count, cb) {

if (name !== 'hotels') { cb(new Error('Invalid data type')); return; }

async.forEach(hotelsData.generateMany(count), function (item, callback) {

var hotel = Hotel.createNew(item);

hotel.save(callback);

}, cb)

}

Page 27: Full Stack Unit Testing

Sample codevar client = null;

function notInitializedThrow () {throw new Error

('Client not initialized')};

module.exports.init = function (config, cb) {

if (client === null) {

client = API.createClient(config);

// doing some initializations tuff

client.on('error', cb);

client.on('connected', cb.bind(this, null));

}

}

module.exports.getClient = function () {

if (client === null) {

return {

method1: notInitializedThrow,

method2: notInitializedThrow

}

} else {

return client;

}

}

Page 28: Full Stack Unit Testing

Essentials

1. Test should not depend on each others

results

2. They should not use shared data (only in

read only mode)

3. Do not allow skipped tests in releases

4. Tests are not just for make it green

Page 29: Full Stack Unit Testing

Integration tests

1. They are checking of how modules are

working together

2. Ideal for checking of entity lifecycle -

creation, linking to others, api calls,

querying, destroying

3. Execution environment should be

configurable

Page 30: Full Stack Unit Testing
Page 31: Full Stack Unit Testing
Page 32: Full Stack Unit Testing

References

Tools:

● WS:o WebSocket API client

● HTTP:o Nock

Article:● https://davidbeath.com/posts/testing-http-responses-in-

nodejs.html

Page 33: Full Stack Unit Testing

Stack

1. Mocha as core framework

2. Chai / Expect as assertions

3. Request.js for HTTP requests

4. node-websocket as ws client

5. Faker or factory-lady for generation of test

data

Page 34: Full Stack Unit Testing

Best

1. To put grunt test or test command as git

merge to master hook

2. To put shortcut for testing into npm test

assuming that grunt is not globally installed

3. JSHint/JSLint as pre commit hook

Page 35: Full Stack Unit Testing

Worst

1. To mix TDD and BDDa. TDD: Suite, test, step, setup, done

b. BDD: Expectations, asserts

2. To spaghetti the dependencies inside test

code

Page 36: Full Stack Unit Testing

Sample codedescribe('API method', function () {

var temporaryData = null;

it('should do one thing', function (done) {

var result = API.call('somemethod');

temporaryData = API.call('anotherMethod');

expect(result).to.have.keys(['code', 'details', 'message']);

});

it('should do another thing', function (done) {

API.call('setup', temporaryData);

var result = API.call('anotherMethod');

expect(result).to.be.null;

Page 37: Full Stack Unit Testing

Pitfalls

1. Separated environment for integration testing, unit

testing development and production

2. Do not rely on synchronous operations especially when

they are not (callbacks, initialization process)

3. Extra console.log’s are breaking unit test reportings

Page 38: Full Stack Unit Testing

Sample codedescribe('Service API', function () {

before(function (done) {

thirdparty1.init(/*callback?*/);

thirdparty2.init(/*callback?*/);

thirdparty3.init(/*callback?*/);

done();

});

before(function (done) {

thirdparty1.done(/*callback?*/);

thirdparty2.done(/*callback?*/);

thirdparty3.done(/*callback?*/);

done();

});

});

describe('Service API', function () {

before(function (done) {

async.waterfall([

thirdparty1.init,

thirdparty2.init,

thirdparty3.init

], done);

});

before(function (done) {

async.waterfall([

thirdparty1.done,

thirdparty2.done,

thirdparty3.done

], done);

});

});

Page 39: Full Stack Unit Testing

References

Books1. Testable Javascript book

2. JavaScript Allongé

3. Testing with CoffeeScript

Articles/Blogs:1. Full spectrum testing with angular.js and Karma

2. Cross-browser testing on multiple devices

3. Mocha + CoffeeScript tutorial

4. http://code.tutsplus.com/tutorials/testing-in-nodejs--net-35018

Page 41: Full Stack Unit Testing

QA