SYSTEM UNDER TESTING
TESTING VARIETY
TESTING TYPES
Black box
Performance
Load testing
Usability testing
End-to-end
White box
Functional
Compatibility
Stress testing
Recovery
Unit testing
Integration
Security testing
Regression
Acceptance
UNIT TESTING PLACE
Unit tests
Integration tests
Acceptance tests
UI tests
TESTING GLOSSARY
FAKE
SPY
STUB
MOCK
TESTING SERVER
WHY START WITH SERVER
Common place to test
Mostly logic
Easier to automate
CHALLENGES ON SERVER
Routing
Database interactions
Knowing what to test
HOW USERS SEE API
Route
Middleware
Business objects
HOW WE TEST API
Middleware
Business objects
Route
SUMMARY
Test only app functionality
Server testing is straightforward
Don't forget to refactor
TESTING CLIENT
CHALLENGES ON CLIENT
User interaction
Framework "Magic"
Appearance
HOW USERS SEE APP
User interface
Data for user interface
Source of data
HOW WE TEST APP
User interface
Data for user interface
Source of data
SUMMARY
Client testing needs change of perspective
Fake out all levels below the current one
Don’t Forget to Refactor
TESTING TOOLS
MOCHA
CHAI
SINON
Sinon.JS
JASMINE
KARMA
JEST
TESTING PRACTICE
DEFINING A MODULE
describe( 'Notes:', function() {
var Notes = window.modules.Notes;
it( 'should Notes module to be defined:', function() {
expect( Notes ).toBeDefined();
} );
} );
DEFINING A MODULE
( function( window ) {
function Notes() {}
window.modules = window.modules || {};
window.modules.Notes = Notes;
} )( window );
INITIALIZING A MODULE
describe( 'Notes:', function() {
var Notes = window.modules.Notes;
it( 'should Notes module to be defined:', function() {
expect( Notes ).toBeDefined();
} );
describe( 'initialization=>', function() {
beforeEach( function() {
env.stub( Notes.prototype, 'bindEvents' );
this.sut = new Notes();
} );
it( 'should bind events:', function() {
expect( this.sut.bindEvents ).toHaveBeenCalled();
} );
} );
} );
INITIALIZING A MODULE
( function( window, $ ) {
function Notes() {
this.init();
}
$.extend( Notes.prototype, {
init: function() {
this.bindEvents();
},
bindEvents: function() {}
} );
window.modules = window.modules || {};
window.modules.Notes = Notes;
} )( window, jQuery );
RESOLVING PROMISES
describe( 'initialization=>', function() {
beforeEach( function() {
this.fakeDeferred = new $.Deferred();
env.stub( Notes.prototype, 'getNotes' );
env.stub( Notes.prototype, 'bindEvents' );
Object.defineProperty( window, 'authReady', {
value: this.fakeDeferred
} );
this.sut = new Notes();
} );
describe( 'user is NOT signed in=>', function() {
beforeEach( function() {
this.fakeDeferred.resolve( { user: { isLoggedIn: false } } );
} );
it( 'should NOT bind events:', function() {
expect( this.sut.bindEvents ).not.toHaveBeenCalled();
} );
it( 'should NOT get notes:', function() {
expect( this.sut.getNotes ).not.toHaveBeenCalled();
} );
} );
describe( 'user is signed in=>', function() {
beforeEach( function() {
this.fakeDeferred.resolve( { user: { isLoggedIn: true } } );
} );
it( 'should bind events:', function() {
expect( this.sut.bindEvents ).toHaveBeenCalled();
} );
it( 'should NOT get notes:', function() {
expect( this.sut.getNotes ).toHaveBeenCalled();
} );
} );
} );
RESOLVING PROMISES
( function( window, $ ) {
function Notes() {
this.init();
}
$.extend( Notes.prototype, {
init: function() {
window.authReady.then( function( auth ) {
if ( !auth.user.isLoggedIn ) {
return;
}
this.getNotes();
this.bindEvents();
}.bind( this ) );
},
bindEvents: function() {},
getNotes: function() {}
} );
window.modules = window.modules || {};
window.modules.Notes = Notes;
} )( window, jQuery );
BINDING EVENTS
describe( 'binding events=>', function() {
beforeEach( function() {
env.stub( Notes.prototype, 'init' );
this.sut = new Notes();
this.sut.$form = {
on: env.stub()
};
} );
it( 'should bind submit handler on save button:', function() {
this.sut.bindEvents();
expect( this.sut.$form.on ).toHaveBeenCalledWith( 'submit', this.sut.onSubmit );
} );
} );
BINDING EVENTS
( function( window, $ ) {
function Notes() {
this.$form = $( '.js-RC-notes' )
this.init();
}
$.extend( Notes.prototype, {
init: function() {
window.authReady.then( function( auth ) {
if ( !auth.user.isLoggedIn ) {
return;
}
this.getNotes();
this.bindEvents();
}.bind( this ) );
},
bindEvents: function() {
this.$form.on( 'submit', $.proxy( this.onSubmit, this ) );
},
getNotes: function() {},
onSubmit: function( event ) {}
} );
window.modules = window.modules || {};
window.modules.Notes = Notes;
} )( window, jQuery );
AJAXING DATA
describe( 'getting notes=>', function() {
beforeEach( function() {
this.fakeParams = {
'race_id': '123',
'horse_id': [ 12, 23 ],
'race_type_code': 'F'
};
this.fakeConfig = {
type: 'GET',
url: '/racecards/ugc',
data: this.fakeParams
};
this.fakeDeferred = new $.Deferred();
env.stub( Notes.prototype, 'init' );
env.stub( Notes.prototype, 'processParams' ).returns( this.fakeParams );
env.stub( $, 'ajax' ).withArgs( this.fakeConfig ).returns( this.fakeDeferred );
this.sut = new Notes();
} );
describe( 'request is successful=>', function() {
beforeEach( function() {
this.fakeSuccessData = {
success: true,
error: 'error message',
data: { 123: {
comment: 'comment',
rating: 'rating',
odds: 'odds',
selection: true
} }
};
env.stub( Notes.prototype, 'getSuccess' );
} );
it( 'should render notes:', function() {
this.sut.getNotes();
this.fakeDeferred.resolve( this.fakeSuccessData );
expect( this.sut.getSuccess ).toHaveBeenCalledWith( this.fakeParams, this.fakeSuccessData );
} );
} );
describe( 'request is failed=>', function() {
beforeEach( function() {
this.fakeErrorData = {
message: 'error message'
};
env.stub( Notes.prototype, 'getError' );
} );
it( 'should handle error:', function() {
this.sut.getNotes();
this.fakeDeferred.reject( this.fakeErrorData );
expect( this.sut.getError ).toHaveBeenCalledWith( this.fakeErrorData );
} );
} );
} );
AJAXING DATA
( function( window, $ ) {
function Notes() {
this.$form = $( '.js-RC-notes' )
this.init();
}
$.extend( Notes.prototype, {
init: function() {
window.authReady.then( function( auth ) {
if ( !auth.user.isLoggedIn ) {
return;
}
this.getNotes();
this.bindEvents();
}.bind( this ) );
},
bindEvents: function() {
this.$form.on( 'submit', $.proxy( this.onSubmit, this ) );
},
getNotes: function() {
var requestParams = this.processParams();
$.ajax( {
type: 'GET',
url: '/racecards/ugc',
data: requestParams
} )
.done( $.proxy( this.getSuccess, this, requestParams ) )
.fail( $.proxy( this.getError, this ) );
},
onSubmit: function( event ) {},
processParams: function() {},
getSuccess: function( requestParams, response ) {},
getError: function( error ) {}
} );
window.modules = window.modules || {};
window.modules.Notes = Notes;
} )( window, jQuery );
QUESTIONS UNDER TESTING
System Under Testing
By Roman Stremedlovskyi
System Under Testing
Unit Testing in JavaScript projects
- 1,486