The whAt When & how's of
unit testing
The What
A unit test is code that executes part of your
production code with an expectation on the result
- Christian Johansen
production code with an expectation on the result
- Christian Johansen
Focusing on one element of the software at a time
- hence the term unit testing
- Martin Fowler
- hence the term unit testing
- Martin Fowler
The Why
Testability is an inherent quality of good design
- C. Johansen
- C. Johansen
The why
TEST TO
FACILITATE CHANGE
TEST For
CONSISTENCY / REGRESSION
MAINTAINABLE CODE
DOCUMENTATION
THE why
Like they say in the circus
DON'T WORK WITHOUT A NET!
THE HOW
1. Take the smallest piece of testable software
2. Isolate it from the remainder of the code
3. Make sure it behaves as you expect
Found a bug?
Write a test
Fix the bug
TDD
Test Driven Development
Because your'e worth it!
Red
Green
Refactor
Uncle Bob's three laws
first law
You may not write production code
until you have written
a failing Unit test
Second LAW
YOU MAY NOT WRITE More
of a Unit test
Than is sufficient to fail
(not compiling=failing)
Third LAW
YOU MAY NOT WRITE more
PRODUCTION CODE
than is sufficient
to pass the failing test
REGULAR EXPRESSIONS
\b((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\b
IPv4 address
\bM{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b
Roman numerals
how?
describe("isIpv4()", function() { it("should ...", function(){ }); });
Transforming DATA
TRANSFORMING DATA
{ data: { fsrf: false, versions: {
"0": { variableInfo: { header: "Foo", executions: [
{id: 1, code: "F0103A"},
{id: 2, code: "F0105C"},
{id: 3, code: null}],
imageUrls: ["http://example.com/img/763498087376276l.jpg"]}}
}}};
{
title: "Foo",
executions: ["F0103A", "F0105C"],
imgUrl: "http://example.com/img/763498087376276.jpg"
}
How?
describe("#transformData", function(){ it("should ...", function(){}); });
Async code
ASYNC CODE
setTimeout(function() { return "value"; }, 500);
App.Module.find = function() { };
HOW?
done (mocha)
spy (sinon)
eventually (chai-as-promised)
cometh
SINON.JS
SPIES, STUBS & MOCKS
SpIES
Record calls and arguments
Proxy original method
var spy = sinon.spy();
var spy = sinon.spy(function);
var spy = sinon.spy(object, "method");
spy.getCall(0).args[0];
spy.called[Count|Once|Twice|Thrice] // true|false
spy.calledWith();
Stubs Spies++
SPIES with pre-programmed behavior
Does not proxy the original method
var ajax = sinon.stub(jQuery, 'ajax');
stub.return[s]
stub.throw[s]
stub.yield[s]
MockS StubS++
Stubs with pre-programmed expectations
testa mot returvärde vs göra ngt
mock.verify()
Rolling your own
sinon.promise = function() {
var promise = {
then: sinon.stub(),
done: sinon.stub(),
fail: sinon.stub(),
always: sinon.stub()
};
promise.then.returns(promise);
promise.done.returns(promise);
promise.fail.returns(promise);
promise.always.returns(promise);
return promise;
};
If a test case won't fail
by it's own -
it's probably not useful
Don't test 2 much!
it's impossible to test everything
When tests drive development
you end up with enough test
Write tests
that force you to write production code
that solves the problem
nothing more
Refactor testcode & go to developer nirvana
USE CODE COVERAGE
TO ANALYSE
AND DESTROY
Good tests === good coverage
Good coverage !== good tests
A tests-last trap
PRACTICE
READ ON
http://cjohansen.no/talks/2011/xp-meetup/
http://martinfowler.com/articles/asyncJS.html
expect("presentation").to.be.complete();
THE END
Unit testing in JavaScript
By Pontus Lundin
Unit testing in JavaScript
The What WHEN & HOW'S OF unit testing
- 879