full stack unit testing
TRANSCRIPT
![Page 1: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/1.jpg)
Full-stack unit-
testingTech talk @ Pause
![Page 2: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/2.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/3.jpg)
Overview of frameworks
![Page 4: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/4.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/5.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/6.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/7.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/8.jpg)
Test runner
Essentials
1. Synchronization between source files
2. Integration of frameworks
3. Debugging
![Page 9: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/9.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/10.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/11.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/12.jpg)
Unit testing stack
![Page 13: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/13.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/14.jpg)
End-2-end testing
![Page 15: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/15.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/16.jpg)
Reporting
![Page 17: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/17.jpg)
![Page 18: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/18.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/19.jpg)
Testing of server side
![Page 20: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/20.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/21.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/22.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/23.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/24.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/25.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/26.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/27.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/28.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/29.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/30.jpg)
![Page 31: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/31.jpg)
![Page 32: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/32.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/33.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/34.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/35.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/36.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/37.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/38.jpg)
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](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/39.jpg)
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 40: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/40.jpg)
Tools
1. Node version manager
2. Mocha
3. Jasmine
4. Karma
5. Istanbul
6. Protractor
7. Selenium
![Page 41: Full Stack Unit Testing](https://reader034.vdocuments.mx/reader034/viewer/2022042512/55a291051a28abd4288b457b/html5/thumbnails/41.jpg)
QA