Date post: | 15-May-2015 |
Category: |
Technology |
Upload: | marco-cedaro |
View: | 771 times |
Download: | 1 times |
back to the frontjavascript tdd is between us
Who are we?Marco Cedaro javascript pirate, arr
Spreaker Frontend Developer
Luca Lischetti8-bit lover and super hero
(almost) Shazam Frontend Developer
Who are we?Marco Cedaro javascript pirate, arr
Spreaker Frontend Developer
Luca Lischetti8-bit lover and super hero
(almost) Shazam Frontend Developer
The content of this workshop do not necessarily reflect the opinion of authors employers
Who are we?Marco Cedaro javascript pirate, arr
Spreaker Frontend Developer
Luca Lischetti8-bit lover and super hero
(almost) Shazam Frontend Developer
The content of this workshop do not necessarily reflect the opinion of authors employersAuthors employers are not responsible in any way of authors bad coding and funny spoken english
I believe I can fly
Fearless & Unconscious
Fearless & Unconscious
But Life Goes On
TDD is about control
and about DESIGN too
The curious case of JavaScript unit testing
Unit Test and Functional Test
Pro/Constest
interaction between libraries
control over
codebase
consistency against
external changes
execution time
test integration
That's the browsers, baby
Unit testing is supposed to test a single atomic “unit”
of functionality without
dependencies on anything else
This is where you start to run into
serious dependency problems due to the interrelation HTML
and CSS
Unit testing is supposed to test a single atomic “unit”
of functionality without
dependencies on anything else
This is where you start to run into
serious dependency problems due to the interrelation HTML
and CSS
Unit testing is supposed to test a single atomic “unit”
of functionality without
dependencies on anything else
What do you test? Usually how the user interface responds
to user input. Actually, the realm of
functional testing
How does it work?
have you seen LOST?
Write a new test
Write a new test
Run test & let it fail
Write a new test
Run test & let it fail
Write the code
Write a new test
Run test & let it fail
Write the code
Run test & let it succeed
Write a new test
Refactor your code
Run test & let it fail
Write the code
Run test & let it succeed
Coding
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
pub.. What?
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$.watch("customEvent", function(obj) {! //DO STUFF});
_$.notify("customEvent");_$.notify("customEvent", { prop : "value" });
_$.watch("customEvent", function(obj) {! //DO STUFF});
_$.notify("customEvent");_$.notify("customEvent", { prop : "value" });
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$.watch("customEvent", function(obj) {! //DO STUFF});
_$.notify("customEvent");_$.notify("customEvent", { prop : "value" });
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function (_) {
return {
notify: function (a, b, c, d) { for (d = -1, c = [].concat(_[a]); c[++d];) c[d](b);
}, watch: function (a, b) {
(_[a] || (_[a] = [])).push(b); }
}
})({});
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
testNotify: function(){!!! ! var a = 0;!! ! _$.watch('testNotify', function(){ a = 1; });! ! _$.notify('testNotify');
! ! assertEquals(1, a);! },! ! !! testNotifyWithMemo: function(){! !! ! var a = 0 ;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! },[...]
[...]
! testNotifyWithMultipleWhatches: function(){!!! ! var a = 0, b = 0;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.watch('testNotify', function(memo){ b = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! ! assertEquals(1, b);! },[...]
[...]
! testNotifyWithMultipleWhatches: function(){!!! ! var a = 0, b = 0;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.watch('testNotify', function(memo){ b = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! ! assertEquals(1, b);! },[...]
[...]
! testNotifyWithMultipleWhatches: function(){!!! ! var a = 0, b = 0;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.watch('testNotify', function(memo){ b = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! ! assertEquals(1, b);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; } ! ! ! ! else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
[...]
testNotifyWithMultipleWhatchesNested: function(){!!! ! var a = 0, b = 0, c=0;!! ! _$.watch('testNotify', function(memo){
a = memo.test;! ! ! _$.watch('testNotify', function(memo){! ! ! ! if (b<2){ b = memo.test; }
else { c = memo.test; }! ! ! });! ! });! !! ! _$.notify('testNotify', {test: 1});! ! assertEquals(1, a);! ! assertEquals(0, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 2});! ! assertEquals(2, a);! ! assertEquals(2, b);! ! assertEquals(0, c);! !! ! _$.notify('testNotify', {test: 3});! ! assertEquals(3, a);! ! assertEquals(2, b);! ! assertEquals(3, c);! },[...]
There's no parachute
There's a major bug, let's take another look at the code...
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }! ! ! registered[event].push(handler);! ! }
};})();
There's no parachute
How would you write a test to check it?
[...]
! testNotifyWithMultipleWhatches: function(){!!! ! var a = 0, b = 0;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.watch('testNotify', function(memo){ b = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! ! assertEquals(1, b);! },[...]
[...]
! testWhatchWithoutHandler: function(){! !! ! var a = 0, b = 0;!! ! _$.watch('testNotify', function(memo){ a = memo.test; });! ! _$.watch('testNotify');! ! _$.watch('testNotify', function(memo){ b = memo.test; });! ! _$.notify('testNotify', {test: 1});
! ! assertEquals(1, a);! ! assertEquals(1, b);! },[...]
_$ = (function() {var registered = {};
return {
! ! notify: function(event, memo) {! ! ! if (registered[event] instanceof Array){! ! ! ! var handlers = [].concat(registered[event]);
! ! ! ! for (var i=0, handler; (handler = handlers[i]); i++){! ! ! ! ! handler.call(this, memo);! ! ! ! }! ! ! }! ! },! ! !! ! watch: function(event, handler) {! ! ! if (handler) {
if (typeof registered[event] === "undefined"){! ! ! ! registered[event] = [];! ! ! }
! ! ! registered[event].push(handler);}
! ! }
};})();
_$ = (function (_) {
return {
notify: function (a, b, c, d) { for (d = -1, c = [].concat(_[a]); c[++d];) c[d](b); },
watch: function (a, b) { if(b)(_[a] || (_[a] = [])).push(b); }
}
})({});
Spy, Stub & Mock
Fake objects & methods
Sinon.js
a function that records arguments,
return value, the value of this and
exception thrown (if any) for all its calls.
Spies
functions (spies) with pre-programmed
behavior.
Stuba function that
records arguments, return value, the value of this and
exception thrown (if any) for all its calls.
Spies
functions (spies) with pre-programmed
behavior.
Stuba function that
records arguments, return value, the value of this and
exception thrown (if any) for all its calls.
Spiesfunctions (spies) with
pre-programmed behavior (stubs) as
well as pre-programmed expectations.
Mock
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SysyemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
"test MyLib Registers To 'SystemOn' Event": function(){! !! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },! ! !! testMyLibLoggedNotLogged: function(){! !! ! var stub = sinon.stub(User, 'isLogged');!! ! stub.returns(true);! ! //DO STUFF && ASSERTIONS
! ! stub.returns(false);! ! //DO STUFF && ASSERTIONS
! },[...]
[...]
testMyLibRegistersToSystemOnEvent: function(){!!! ! var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! assertTrue(spy.calledWith('SystemOn'));! },[...]
[...]
//testMyLibRegistersToSystemOnEvent: function(){! !! ! //var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! //assertTrue(spy.calledWith('SysyemOn'));! //},!! testMyLibRegistersToSystemOnEvent: function(){!!! ! var mock = sinon.mock(_$);! ! mock.expect('watch').calledWith('SysyemOn');! ! //DO STUFF TO INIT YOUR LIB! ! mock.verify();! },[...]
[...]
//testMyLibRegistersToSystemOnEvent: function(){! !! ! //var spy = sinon.spy(_$, 'watch');!! ! //DO STUFF TO INIT YOUR LIB! ! //assertTrue(spy.calledWith('SysyemOn'));! //},!! testMyLibRegistersToSystemOnEvent: function(){!!! ! var mock = sinon.mock(_$);! ! mock.expect('watch').calledWith('SysyemOn');! ! //DO STUFF TO INIT YOUR LIB! ! mock.verify();! },[...]
What are we going to do
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
svn co https://svn.dsgn.it/jstdd
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
/config/browsers.prop
build.xml
default.prop
svn co https://svn.dsgn.it/jstdd
/libs/base.js
sinon.js
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
/config/browsers.prop
build.xml
default.prop
svn co https://svn.dsgn.it/jstdd
/libs/base.js
sinon.js
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
/tools/ant
browser
jslint
JsTestDriver
/config/browsers.prop
build.xml
default.prop
svn co https://svn.dsgn.it/jstdd
/libs/base.js
sinon.js
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
/tools/ant
browser
jslint
JsTestDriver
/workshop/append
find
syntax
/config/browsers.prop
build.xml
default.prop
svn co https://svn.dsgn.it/jstdd
/libs/base.js
sinon.js
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
/tools/ant
browser
jslint
JsTestDriver
/workshop/append
find
syntax
/append/src
append.js
test
append.test.js
jsTestDriver.conf
/config/browsers.prop
build.xml
default.prop
svn co https://svn.dsgn.it/jstdd
/libs/base.js
sinon.js
cheat
config
dist
libs
tools
workshop
build.sh
build.bat
readme.txt
/tools/ant
browser
jslint
JsTestDriver
/workshop/append
find
syntax
/append/src
append.js
test
append.test.js
jsTestDriver.conf
/config/browsers.prop
build.xml
default.prop
svn co https://svn.dsgn.it/jstdd
build append | sh build.sh append
A simple modular event driven appa javascript code highlighter with 3 components:
syntax highlighterselected word highlighterfinder
First step - syntaxwatch a SRC_LOADED event with the memo {file:'{{FILE_SRC}}'}
highlight (wrap in a span with the keyword itself as classname)
function => <span class="function">function</span>
var, if ... else, for, return, ...
notify SRC_READY with the memo {file:'{{EDITED_SRC}}'}
Second step - appendwatch previous SRC_READY
create a div[id="src_container"] and fill it with the source
append to document
llisten dblclick event and notify SRC_HIGHLIGHT with this memo: {keyword:'{{HIGHLIGHTED_WORD}}'}
manage the SRC_HIGHLIGHT notification <span class="highlight">{{HIGHLIGHTED_KEYWORKD}}</span>
Third step - findwatch to SRC_READY
create a div[id=form] and append inside of it
input[type=text][id=search]
input[type=button][id=submitBtn][value=Search]
append the div to the document
on click on submit notify a SRC_HIGHLIGHT event with memo {keyword:"{{SEARCHED_TEXT}}"}
Where are we now?
Costs of change
I Build So Consistently
I Build So Consistently
Identify Build
Share make it Continuous