3. AGENDA
Unit Testing Concept
Pros & Cons
Basic Terms & Structure
TDD &/vs. BDD
Tools & Libraries
Unit Testing Specifics
in JavaScript
Best Practices
4. UNIT TESTING CONCEPT
Unit testing is a method by which individual
units of source code are tested to determine
if they are fit for use.
5. WHY UNIT TESTING?
Unit tests find problems early in the
development cycle (TDD & BDD)
Refactoring
Integration
Documentation
Better design
6. IS UNIT TESTING A GOOD INVESTMENT?
slow down the development process
share the same blind spots with the code
doesn’t prove that they’re compatible with
one another or configured correctly
8. In simple words, the goal of assertion is to
forcefully define if the test fails or passes.
STATEMENT PASSES FAILS
x = 1 assert(x > 0) assert(x < 0)
expect(4+5).to.equal(9);
ASSERTION
9. function initialize() {
// The initialization was successful.
return true;
}
Given the function initialize():
ASSERTION: EXAMPLE
10. ASSERTION: EXAMPLE
var isInitialized = initialize();
TDD assert.isTrue(isInitialized)
BDD expect(isInitialized).to.be.true
Check that function initialize() returns true
when called.
11. FIXTURE
A test fixture is a fixed state of the software
under test used as a baseline for running
tests.
In JavaScript for client side:
simulate AJAX responses;
loading known set of data such as html
objects.
12. FIXTURE: EXAMPLE
Require the piece of markup stored in
myfixturemarkup.html file before each test:
beforeEach(function() {
loadFixtures('myfixturemarkup.html');
});
14. STUB: EXAMPLE
Forcing a method to throw an error in order
to test error handling.
var fn = foo.stub().throws(Error);
expect(fn).to.throw(Error);
15. SPY
A test spy is a
function that
records
arguments,
return value, the
value of this and
exception thrown
(if any) for all its
calls.
16. SPY: EXAMPLE
Test that a function cursor.hide() has been
only called once, and only once.
sinon.spy(cursor, "hide");
TDD sinon.assert.calledOnce(cursor.hide)
BDD expect(cursor.hide.calledOnce).to.be.true
17. MOCK
Mocks are fake objects with pre-
programmed behavior (like stubs) and
pre-programmed expectations.
They are like both stubs and spies – in
one.
18. MOCK: EXAMPLE
Create an expectation that jQuery.each is
called once, and only once, and also
instructs the mock to behave as we pre-
define.
var mock = sinon.mock(jQuery);
19. MOCK: EXAMPLE
#1 – which method?
#2 – how many times it is called?
#3 – what are the arguments when the
method called?
#4 – what the method returns?
25. Before / BeforeEach
before(function() { console.log(‘before test’); });
test(‘first test’, function() { console.log(‘first test’); });
test(‘second test’, function() { console.log(‘second test’);});
afterEach(function() { console.log(‘after each test’); });
Result
before test
first test
after each test
second test
after each test
BASIC STRUCTURE: EXPLAINED
26. BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom
level.',
#2. Prepare an input and predicted result.
var minZoomLevel = 1;
var zoomLevel = minZoomLevel + 0.1;
var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method.
var actualCursor = cursor.init(zoomLevel);
#4. Check an output.
expect(actualCursor).to.deep.equal(expectedCursor);
done();
});
function(done) {
27. BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom
level.',
#2. Prepare an input and predicted result.
var minZoomLevel = 1;
var zoomLevel = minZoomLevel + 0.1;
var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method.
var actualCursor = cursor.init(zoomLevel);
#4. Check an output.
expect(actualCursor).to.deep.equal(expectedCursor);
done();
});
function(done) {
28. BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom
level.',
#2. Prepare an input and predicted result.
var minZoomLevel = 1;
var zoomLevel = minZoomLevel + 0.1;
var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method.
var actualCursor = cursor.init(zoomLevel);
#4. Check an output.
expect(actualCursor).to.deep.equal(expectedCursor);
done();
});
function(done) {
29. BASIC STRUCTURE: EXPLAINED
it('should initialize cursor if zoom level >= minimum zoom
level.',
#2. Prepare an input and predicted result.
var minZoomLevel = 1;
var zoomLevel = minZoomLevel + 0.1;
var expectedCursor = {‘color’: ‘white’, ‘height’: … };
#3. Call a method.
var actualCursor = cursor.init(zoomLevel);
#4. Check an output.
expect(actualCursor).to.deep.equal(expectedCursor);
done();
});
function(done) {
37. HOW DO I UNIT TEST
Known Frameworks / Libraries?
What to test? What to use?
Angular, React, Flight Karma + Jasmine
Backbone qUnit
Ember Karma + qUnit (ember-app-kit)
ExtJs Jasmine, Siesta (UI)
TypeScript tsUnit
CoffeeScript qUnit
Dart Unittest, Hop and Drone.io
NodeJs expresso and vows, Nodeunit
38. TOOLS: WHAT WE USE
Run UT: Mocha
Run UT in parallel: Macchiato
Assert/Expect: Chai
W3C DOM in JavaScript: Jsdom
Mock, spy, stub: Sinon
Code coverage tool: None
Routine automation: make/Grunt
47. WRAPPING UP
Each test verifies a small chunk of code
Unit tests work best in isolation
Mocks, stubs and spies help to isolate test
Don’t test everything but write many tests
> 40 tools are available to ease unit testing
experience, so CHOOSE YOUR OWN!