Slide 1

Slide 1 text

back to the front javascript tdd is between us

Slide 2

Slide 2 text

Who are we? Marco Cedaro javascript pirate, arr Spreaker Frontend Developer Luca Lischetti 8-bit lover and super hero (almost) Shazam Frontend Developer

Slide 3

Slide 3 text

Who are we? Marco Cedaro javascript pirate, arr Spreaker Frontend Developer Luca Lischetti 8-bit lover and super hero (almost) Shazam Frontend Developer The content of this workshop do not necessarily reflect the opinion of authors employers

Slide 4

Slide 4 text

Who are we? Marco Cedaro javascript pirate, arr Spreaker Frontend Developer Luca Lischetti 8-bit lover and super hero (almost) Shazam Frontend Developer The content of this workshop do not necessarily reflect the opinion of authors employers Authors employers are not responsible in any way of authors bad coding and funny spoken english

Slide 5

Slide 5 text

I believe I can fly

Slide 6

Slide 6 text

Fearless & Unconscious

Slide 7

Slide 7 text

Fearless & Unconscious

Slide 8

Slide 8 text

But Life Goes On

Slide 9

Slide 9 text

TDD is about control

Slide 10

Slide 10 text

and about DESIGN too

Slide 11

Slide 11 text

The curious case of JavaScript unit testing

Slide 12

Slide 12 text

Unit Test and Functional Test

Slide 13

Slide 13 text

Pro/Cons test interaction between libraries control over codebase consistency against external changes execution time test integration

Slide 14

Slide 14 text

That's the browsers, baby

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Unit testing is supposed to test a single atomic “unit” of functionality without dependencies on anything else

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

How does it work?

Slide 20

Slide 20 text

have you seen LOST?

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

Write a new test

Slide 23

Slide 23 text

Write a new test Run test & let it fail

Slide 24

Slide 24 text

Write a new test Run test & let it fail Write the code

Slide 25

Slide 25 text

Write a new test Run test & let it fail Write the code Run test & let it succeed

Slide 26

Slide 26 text

Write a new test Refactor your code Run test & let it fail Write the code Run test & let it succeed

Slide 27

Slide 27 text

Coding

Slide 28

Slide 28 text

_$ = (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); ! ! } }; })();

Slide 29

Slide 29 text

pub.. What?

Slide 30

Slide 30 text

_$ = (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); ! ! } }; })();

Slide 31

Slide 31 text

_$.watch("customEvent", function(obj) { ! //DO STUFF }); _$.notify("customEvent"); _$.notify("customEvent", { prop : "value" });

Slide 32

Slide 32 text

_$.watch("customEvent", function(obj) { ! //DO STUFF }); _$.notify("customEvent"); _$.notify("customEvent", { prop : "value" });

Slide 33

Slide 33 text

_$ = (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); ! ! } }; })();

Slide 34

Slide 34 text

_$ = (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); ! ! } }; })();

Slide 35

Slide 35 text

_$ = (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); ! ! } }; })();

Slide 36

Slide 36 text

_$ = (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); ! ! } }; })();

Slide 37

Slide 37 text

_$ = (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); ! ! } }; })();

Slide 38

Slide 38 text

_$ = (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); ! ! } }; })();

Slide 39

Slide 39 text

_$.watch("customEvent", function(obj) { ! //DO STUFF }); _$.notify("customEvent"); _$.notify("customEvent", { prop : "value" });

Slide 40

Slide 40 text

_$ = (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); ! ! } }; })();

Slide 41

Slide 41 text

_$ = (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); ! ! } }; })();

Slide 42

Slide 42 text

_$ = (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); ! ! } }; })();

Slide 43

Slide 43 text

_$ = (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); ! ! } }; })();

Slide 44

Slide 44 text

_$ = (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); ! ! } }; })();

Slide 45

Slide 45 text

_$ = (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); ! ! } }; })();

Slide 46

Slide 46 text

_$ = (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); ! ! } }; })();

Slide 47

Slide 47 text

_$ = (function (_) { 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); }, })({});

Slide 48

Slide 48 text

[...] 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); ! }, [...]

Slide 49

Slide 49 text

[...] 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); ! }, [...]

Slide 50

Slide 50 text

[...] 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); ! }, [...]

Slide 51

Slide 51 text

[...] 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); ! }, [...]

Slide 52

Slide 52 text

[...] 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); ! }, [...]

Slide 53

Slide 53 text

[...] 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); ! }, [...]

Slide 54

Slide 54 text

[...] 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); ! }, [...]

Slide 55

Slide 55 text

[...] ! 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); ! }, [...]

Slide 56

Slide 56 text

[...] ! 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); ! }, [...]

Slide 57

Slide 57 text

[...] ! 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); ! }, [...]

Slide 58

Slide 58 text

[...] 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); ! }, [...]

Slide 59

Slide 59 text

[...] 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); ! }, [...]

Slide 60

Slide 60 text

[...] 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); ! }, [...]

Slide 61

Slide 61 text

[...] 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); ! }, [...]

Slide 62

Slide 62 text

[...] 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); ! }, [...]

Slide 63

Slide 63 text

[...] 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); ! }, [...]

Slide 64

Slide 64 text

[...] 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); ! }, [...]

Slide 65

Slide 65 text

[...] 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); ! }, [...]

Slide 66

Slide 66 text

[...] 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); ! }, [...]

Slide 67

Slide 67 text

[...] 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); ! }, [...]

Slide 68

Slide 68 text

There's no parachute There's a major bug, let's take another look at the code...

Slide 69

Slide 69 text

_$ = (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); ! ! } }; })();

Slide 70

Slide 70 text

_$ = (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); ! ! } }; })();

Slide 71

Slide 71 text

There's no parachute How would you write a test to check it?

Slide 72

Slide 72 text

[...] ! 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); ! }, [...]

Slide 73

Slide 73 text

[...] ! 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); ! }, [...]

Slide 74

Slide 74 text

_$ = (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); } ! ! } }; })();

Slide 75

Slide 75 text

_$ = (function (_) { 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); }, })({});

Slide 76

Slide 76 text

Spy, Stub & Mock

Slide 77

Slide 77 text

Fake objects & methods

Slide 78

Slide 78 text

Sinon.js

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls. Spies

Slide 81

Slide 81 text

functions (spies) with pre-programmed behavior. Stub a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls. Spies

Slide 82

Slide 82 text

functions (spies) with pre-programmed behavior. Stub 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 (stubs) as well as pre- programmed expectations. Mock

Slide 83

Slide 83 text

[...] 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 ! }, [...]

Slide 84

Slide 84 text

[...] 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 ! }, [...]

Slide 85

Slide 85 text

[...] "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 ! }, [...]

Slide 86

Slide 86 text

[...] 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 ! }, [...]

Slide 87

Slide 87 text

[...] 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 ! }, [...]

Slide 88

Slide 88 text

[...] 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 ! }, [...]

Slide 89

Slide 89 text

[...] 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 ! }, [...]

Slide 90

Slide 90 text

[...] 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 ! }, [...]

Slide 91

Slide 91 text

[...] 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 ! }, [...]

Slide 92

Slide 92 text

[...] 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 ! }, [...]

Slide 93

Slide 93 text

[...] testMyLibRegistersToSystemOnEvent: function(){! ! ! ! var spy = sinon.spy(_$, 'watch');! ! ! //DO STUFF TO INIT YOUR LIB ! ! assertTrue(spy.calledWith('SystemOn')); ! }, [...]

Slide 94

Slide 94 text

[...] //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(); ! }, [...]

Slide 95

Slide 95 text

[...] //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(); ! }, [...]

Slide 96

Slide 96 text

What are we going to do

Slide 97

Slide 97 text

cheat config dist libs tools workshop build.sh build.bat readme.txt svn co https://svn.dsgn.it/jstdd

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

/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

Slide 100

Slide 100 text

/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

Slide 101

Slide 101 text

/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

Slide 102

Slide 102 text

/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

Slide 103

Slide 103 text

/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

Slide 104

Slide 104 text

A simple modular event driven app a javascript code highlighter with 3 components: syntax highlighter selected word highlighter finder

Slide 105

Slide 105 text

First step - syntax watch a SRC_LOADED event with the memo {file:'{{FILE_SRC}}'} highlight (wrap in a span with the keyword itself as classname) function => function var, if ... else, for, return, ... notify SRC_READY with the memo {file:'{{EDITED_SRC}}'}

Slide 106

Slide 106 text

Second step - append watch 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 {{HIGHLIGHTED_KEYWORKD}}

Slide 107

Slide 107 text

Third step - find watch 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}}"}

Slide 108

Slide 108 text

Where are we now?

Slide 109

Slide 109 text

Costs of change

Slide 110

Slide 110 text

I Build So Consistently

Slide 111

Slide 111 text

I Build So Consistently Identify Build Share make it Continuous

Slide 112

Slide 112 text

No content