Slide 1

Slide 1 text

UNIT testing js Saturday, 5 November, 11

Slide 2

Slide 2 text

@dmosher Saturday, 5 November, 11

Slide 3

Slide 3 text

testing sucks Saturday, 5 November, 11

Slide 4

Slide 4 text

testing sucks Saturday, 5 November, 11

Slide 5

Slide 5 text

testing sucks js Saturday, 5 November, 11

Slide 6

Slide 6 text

testing sucks js php Saturday, 5 November, 11

Slide 7

Slide 7 text

testing sucks js php ??? Saturday, 5 November, 11

Slide 8

Slide 8 text

Saturday, 5 November, 11

Slide 9

Slide 9 text

because Saturday, 5 November, 11

Slide 10

Slide 10 text

because don’t want to Saturday, 5 November, 11

Slide 11

Slide 11 text

because don’t want to jaded Saturday, 5 November, 11

Slide 12

Slide 12 text

because don’t want to don’t know how jaded Saturday, 5 November, 11

Slide 13

Slide 13 text

because don’t want to afraid don’t know how jaded Saturday, 5 November, 11

Slide 14

Slide 14 text

because don’t want to afraid don’t know how jaded ? Saturday, 5 November, 11

Slide 15

Slide 15 text

every developer shares a secret FEAR Saturday, 5 November, 11

Slide 16

Slide 16 text

MY CODE SUCKS? what if Saturday, 5 November, 11

Slide 17

Slide 17 text

AND WE COPE POORLY Saturday, 5 November, 11

Slide 18

Slide 18 text

fear causes us to: Saturday, 5 November, 11

Slide 19

Slide 19 text

fear causes us to: pair less Saturday, 5 November, 11

Slide 20

Slide 20 text

fear causes us to: pair less share less Saturday, 5 November, 11

Slide 21

Slide 21 text

fear causes us to: pair less share less change less Saturday, 5 November, 11

Slide 22

Slide 22 text

fear causes us to: Saturday, 5 November, 11

Slide 23

Slide 23 text

fear causes us to: defer more Saturday, 5 November, 11

Slide 24

Slide 24 text

fear causes us to: defer more defend more Saturday, 5 November, 11

Slide 25

Slide 25 text

fear causes us to: defer more defend more deflect more Saturday, 5 November, 11

Slide 26

Slide 26 text

say it with me: Saturday, 5 November, 11

Slide 27

Slide 27 text

say it with me: “my code sucks” Saturday, 5 November, 11

Slide 28

Slide 28 text

so fail Saturday, 5 November, 11

Slide 29

Slide 29 text

so fail PROUDLY Saturday, 5 November, 11

Slide 30

Slide 30 text

so fail Saturday, 5 November, 11

Slide 31

Slide 31 text

so fail FASTER Saturday, 5 November, 11

Slide 32

Slide 32 text

Saturday, 5 November, 11

Slide 33

Slide 33 text

because Saturday, 5 November, 11

Slide 34

Slide 34 text

because YOUR CODE CAN SUCK Saturday, 5 November, 11

Slide 35

Slide 35 text

because YOUR CODE CAN SUCK IF YOU HAVE Saturday, 5 November, 11

Slide 36

Slide 36 text

because YOUR CODE CAN SUCK TESTS IF YOU HAVE Saturday, 5 November, 11

Slide 37

Slide 37 text

because YOUR CODE CAN SUCK TESTS IF YOU HAVE sort of ... Saturday, 5 November, 11

Slide 38

Slide 38 text

YOUR CODE CAN SUCK TESTS IF YOU HAVE sort of ... Saturday, 5 November, 11

Slide 39

Slide 39 text

TESTS IF YOU HAVE sort of ... Saturday, 5 November, 11

Slide 40

Slide 40 text

IF YOU HAVE sort of ... Saturday, 5 November, 11

Slide 41

Slide 41 text

sort of ... Saturday, 5 November, 11

Slide 42

Slide 42 text

with tests my code can suck Saturday, 5 November, 11

Slide 43

Slide 43 text

with tests my code can suck safety net Saturday, 5 November, 11

Slide 44

Slide 44 text

with tests my code can suck safety net freedom to unsuck Saturday, 5 November, 11

Slide 45

Slide 45 text

with tests my code can suck safety net freedom to unsuck change verified Saturday, 5 November, 11

Slide 46

Slide 46 text

with tests my code can suck safety net freedom to unsuck change verified commit Saturday, 5 November, 11

Slide 47

Slide 47 text

and that’s why Saturday, 5 November, 11

Slide 48

Slide 48 text

testing rocks Saturday, 5 November, 11

Slide 49

Slide 49 text

testing rocks Saturday, 5 November, 11

Slide 50

Slide 50 text

testing rocks js Saturday, 5 November, 11

Slide 51

Slide 51 text

Saturday, 5 November, 11

Slide 52

Slide 52 text

if it not a unit test Saturday, 5 November, 11

Slide 53

Slide 53 text

if it talks to the db not a unit test Saturday, 5 November, 11

Slide 54

Slide 54 text

if it talks to the db talks across network not a unit test Saturday, 5 November, 11

Slide 55

Slide 55 text

if it talks to the db talks across network won’t run out of order not a unit test Saturday, 5 November, 11

Slide 56

Slide 56 text

if it talks to the db talks across network touches the filesystem won’t run out of order not a unit test Saturday, 5 November, 11

Slide 57

Slide 57 text

unit test if it Saturday, 5 November, 11

Slide 58

Slide 58 text

isolates boundaries unit test if it Saturday, 5 November, 11

Slide 59

Slide 59 text

isolates boundaries mocks dependencies unit test if it Saturday, 5 November, 11

Slide 60

Slide 60 text

isolates boundaries mocks dependencies FFFFFFAAAAAAAAAST unit test if it Saturday, 5 November, 11

Slide 61

Slide 61 text

isolates boundaries mocks dependencies allows for fast feedback FFFFFFAAAAAAAAAST unit test if it Saturday, 5 November, 11

Slide 62

Slide 62 text

RECAP Saturday, 5 November, 11

Slide 63

Slide 63 text

Saturday, 5 November, 11

Slide 64

Slide 64 text

embrace fear ... code sucks Saturday, 5 November, 11

Slide 65

Slide 65 text

embrace fear ... code sucks tests === freedom Saturday, 5 November, 11

Slide 66

Slide 66 text

embrace fear ... code sucks tests === freedom if Saturday, 5 November, 11

Slide 67

Slide 67 text

embrace fear ... code sucks tests === freedom fast, isolating, units if Saturday, 5 November, 11

Slide 68

Slide 68 text

now that we all love testing ... :) Saturday, 5 November, 11

Slide 69

Slide 69 text

SHIFT architectures Saturday, 5 November, 11

Slide 70

Slide 70 text

security persisting data analytics application logic HTML templating routing users proxying UI events things servers are great at Saturday, 5 November, 11

Slide 71

Slide 71 text

security persisting data analytics application logic HTML templating routing users proxying things servers are great at Saturday, 5 November, 11

Slide 72

Slide 72 text

security persisting data analytics HTML templating routing users proxying things servers are great at Saturday, 5 November, 11

Slide 73

Slide 73 text

security persisting data analytics routing users proxying things servers are great at Saturday, 5 November, 11

Slide 74

Slide 74 text

security persisting data analytics proxying things servers are great at Saturday, 5 November, 11

Slide 75

Slide 75 text

it’s simpler when the client handles Saturday, 5 November, 11

Slide 76

Slide 76 text

UI events it’s simpler when the client handles Saturday, 5 November, 11

Slide 77

Slide 77 text

application logic UI events it’s simpler when the client handles Saturday, 5 November, 11

Slide 78

Slide 78 text

application logic HTML templating UI events it’s simpler when the client handles Saturday, 5 November, 11

Slide 79

Slide 79 text

application logic HTML templating routing users UI events it’s simpler when the client handles Saturday, 5 November, 11

Slide 80

Slide 80 text

BDD for JavaScript Saturday, 5 November, 11

Slide 81

Slide 81 text

Saturday, 5 November, 11

Slide 82

Slide 82 text

don’t Saturday, 5 November, 11

Slide 83

Slide 83 text

don’t test jQuery Saturday, 5 November, 11

Slide 84

Slide 84 text

don’t hit your server test jQuery Saturday, 5 November, 11

Slide 85

Slide 85 text

don’t hit your server write async specs test jQuery Saturday, 5 November, 11

Slide 86

Slide 86 text

don’t hit your server test native DOM apis write async specs test jQuery Saturday, 5 November, 11

Slide 87

Slide 87 text

Logout $(‘.logout’).click(function() { alert('cats'); }); don’t test jQuery Saturday, 5 November, 11

Slide 88

Slide 88 text

Logout $(‘.logout’).click(function() { alert('cats'); }); it(‘binds the click event’, function() { spyOn(window, ‘alert’); $(‘.logout’).trigger(‘click’); // yuck expect(window.alert).toHaveBeenCalledWith(‘cats’); }); don’t test jQuery Saturday, 5 November, 11

Slide 89

Slide 89 text

Logout var logout = function() { alert('cats'); }; $(‘.logout’).click(logout); don’t test jQuery Saturday, 5 November, 11

Slide 90

Slide 90 text

Logout var logout = function() { alert('cats'); }; $(‘.logout’).click(logout); it(‘says cats’, function() { spyOn(window, ‘alert’); logout(); // test the unit directly expect(window.alert).toHaveBeenCalledWith(‘cats’); }); don’t test jQuery Saturday, 5 November, 11

Slide 91

Slide 91 text

don’t hit your server var getDogs = function() { $.post(‘/get/dog’, function(dog) { $(‘ul.dog’).append(‘
  • ’ + dog + ‘
  • ’); }); }; don’t write async specs Saturday, 5 November, 11

    Slide 92

    Slide 92 text

    don’t hit your server var getDogs = function() { $.post(‘/get/dog’, function(dog) { $(‘ul.dog’).append(‘
  • ’ + dog + ‘
  • ’); }); }; it(‘hits my server’, function() { runs(function() { getDogs(); // yuck }); waits(500); // yuck runs(function() { // yuck expect($(‘ul.dogs’)).toContain(‘li.dog’); }); }); don’t write async specs Saturday, 5 November, 11

    Slide 93

    Slide 93 text

    don’t hit your server don’t write async specs Saturday, 5 November, 11

    Slide 94

    Slide 94 text

    var getDogs = function() { $.post(‘/get/dog’, renderDog); }; var renderDog = function(dog) { $(‘ul.dog’).append(‘
  • ’ + dog + ‘
  • ’); } don’t hit your server don’t write async specs Saturday, 5 November, 11

    Slide 95

    Slide 95 text

    var getDogs = function() { $.post(‘/get/dog’, renderDog); }; var renderDog = function(dog) { $(‘ul.dog’).append(‘
  • ’ + dog + ‘
  • ’); } it(‘fetches a dog’, function() { // separation of concerns spyOn($, ‘post’); getDogs(); expect($.post).toHaveBeenCalledWith(‘/get/dog’, renderDogs); }); don’t hit your server don’t write async specs Saturday, 5 November, 11

    Slide 96

    Slide 96 text

    var getDogs = function() { $.post(‘/get/dog’, renderDog); }; var renderDog = function(dog) { $(‘ul.dog’).append(‘
  • ’ + dog + ‘
  • ’); } it(‘fetches a dog’, function() { // separation of concerns spyOn($, ‘post’); getDogs(); expect($.post).toHaveBeenCalledWith(‘/get/dog’, renderDogs); }); it(‘renders a dog’, function() { // isolated units renderDog(‘charlie’); expect($(ul.dog).find(‘.dog’)).toHaveText(‘charlie’); }); don’t hit your server don’t write async specs Saturday, 5 November, 11

    Slide 97

    Slide 97 text

    don’t test native DOM apis var loginView = function() { window.location.pathname = ‘/login’; }; Saturday, 5 November, 11

    Slide 98

    Slide 98 text

    don’t test native DOM apis var loginView = function() { window.location.pathname = ‘/login’; }; it(‘messes up my test runner’, function() { loginView(); expect(window.location.pathname).toBe(‘/login’); }); Saturday, 5 November, 11

    Slide 99

    Slide 99 text

    don’t test native DOM apis var redirectTo = function(spot) { // create a wrapper window.location.pathname = spot; } var loginView = function() { redirectTo(‘/login’); // use the wrapper in our unit }; Saturday, 5 November, 11

    Slide 100

    Slide 100 text

    don’t test native DOM apis var redirectTo = function(spot) { // create a wrapper window.location.pathname = spot; } var loginView = function() { redirectTo(‘/login’); // use the wrapper in our unit }; it(‘redirects to /login’, function() { spyOn(window, ‘redirectTo’); // mock our dependency loginView(); expect(redirectTo).toHaveBeenCalledWith(‘/login’); // win :) }); Saturday, 5 November, 11

    Slide 101

    Slide 101 text

    do Saturday, 5 November, 11

    Slide 102

    Slide 102 text

    do spyOn($, ‘ajax’); Saturday, 5 November, 11

    Slide 103

    Slide 103 text

    do spyOn($, ‘ajax’); mock html templates Saturday, 5 November, 11

    Slide 104

    Slide 104 text

    do spyOn($, ‘ajax’); mock html templates test the “plumbing” Saturday, 5 November, 11

    Slide 105

    Slide 105 text

    do spyOn($, ‘ajax’); mock html templates write and test wrappers test the “plumbing” Saturday, 5 November, 11

    Slide 106

    Slide 106 text

    dospyOn($, ‘ajax’); var getDogs = function() { $.ajax({ // declarative and explicit arguments url: ‘/get/dog’, success: renderDog }); }; Saturday, 5 November, 11

    Slide 107

    Slide 107 text

    dospyOn($, ‘ajax’); var getDogs = function() { $.ajax({ // declarative and explicit arguments url: ‘/get/dog’, success: renderDog }); }; it(‘fetches a dog’, function() { // separation of concerns spyOn($, ‘ajax’); getDogs(); expect($.ajax).toHaveBeenCalledWith({ url: ‘/get/dog’, success: renderDogs }); }); Saturday, 5 November, 11

    Slide 108

    Slide 108 text

    <li class=”user”>{{name}}</li>
      var renderUser = function(name) { var t = _.template($(‘#user-tpl’).html()); // probably elsewhere $(‘.users’).append(t({name:name}); } do mock html templates dotest the “plumbing” Saturday, 5 November, 11

      Slide 109

      Slide 109 text

      <li class=”user”>{{name}}</li>
        var renderUser = function(name) { var t = _.template($(‘#user-tpl’).html()); // probably elsewhere $(‘.users’).append(t({name:name}); } it(‘verifies too much and depends on the real DOM’, function() { var $users = $(‘.users’); renderUser(‘nate’); expect($users).toContain(‘li.user’); // limits refactoring expect($users.find(‘.user’)).toHaveText(‘nate’); }); do mock html templates dotest the “plumbing” Saturday, 5 November, 11

        Slide 110

        Slide 110 text

        <li class=”user”>{{name}}</li>
          var renderUser = function(name) { var t = _.template($(‘#user-tpl’).html()); $(‘.users’).append(t({name:name}); } do mock html templates dotest the “plumbing” Saturday, 5 November, 11

          Slide 111

          Slide 111 text

          <li class=”user”>{{name}}</li>
            var renderUser = function(name) { var t = _.template($(‘#user-tpl’).html()); $(‘.users’).append(t({name:name}); } it(‘tests the plumbing’, function() { // tests only the keys/vals var $users = inject(‘ul.users’); // inject isolates btwn tests injectTemplate(‘#user-tpl’, [‘name’]); // emits {{name}} renderUser(‘nate’); expect($users).toHaveText(‘nate’); // refactor markup easier }); do mock html templates dotest the “plumbing” Saturday, 5 November, 11

            Slide 112

            Slide 112 text

            do write and test wrappers var redirectTo = function(spot) { // create a wrapper window.location.pathname = spot; } var loginView = function() { redirectTo(‘/login’); // use the wrapper in our unit }; Saturday, 5 November, 11

            Slide 113

            Slide 113 text

            do write and test wrappers var redirectTo = function(spot) { // create a wrapper window.location.pathname = spot; } var loginView = function() { redirectTo(‘/login’); // use the wrapper in our unit }; it(‘redirects to /login’, function() { spyOn(window, ‘redirectTo’); // mock our dependency loginView(); expect(window.redirectTo).toHaveBeenCalledWith(‘/login); // win :) }); Saturday, 5 November, 11

            Slide 114

            Slide 114 text

            limit Saturday, 5 November, 11

            Slide 115

            Slide 115 text

            limitcallback nesting Saturday, 5 November, 11

            Slide 116

            Slide 116 text

            limitcallback nesting anonymous functions Saturday, 5 November, 11

            Slide 117

            Slide 117 text

            limitcallback nesting DOM verification anonymous functions Saturday, 5 November, 11

            Slide 118

            Slide 118 text

            limit callback nesting Saturday, 5 November, 11

            Slide 119

            Slide 119 text

            limit callback nesting $.post(‘/level/1’, function(shallow) { $.post(‘/level/2’, function(deep) { doSomething(shallow); $.post(‘/level/3’, function(deeper) { doSomething(deep); $.post(‘/level/4’, function(deepest) { doSomething(deeper); doSomething(deepest); console.log(“INCEPTION”); }); }); }); }); // what is this i don’t even Saturday, 5 November, 11

            Slide 120

            Slide 120 text

            limit callback nesting Saturday, 5 November, 11

            Slide 121

            Slide 121 text

            limit callback nesting $.post(‘/level/1’, function(shallow) { APP.trigger(‘level-one-complete’, shallow); }); Saturday, 5 November, 11

            Slide 122

            Slide 122 text

            limit callback nesting $.post(‘/level/1’, function(shallow) { APP.trigger(‘level-one-complete’, shallow); }); APP.bind(‘level-one-complete’, function(shallow) { doSomething(shallow); $.post(‘/level/2’, function(deep) { APP.trigger(‘level-two-complete’, deep); }); }); Saturday, 5 November, 11

            Slide 123

            Slide 123 text

            limit callback nesting $.post(‘/level/1’, function(shallow) { APP.trigger(‘level-one-complete’, shallow); }); APP.bind(‘level-one-complete’, function(shallow) { doSomething(shallow); $.post(‘/level/2’, function(deep) { APP.trigger(‘level-two-complete’, deep); }); }); etc... (but don’t use $.post!) Saturday, 5 November, 11

            Slide 124

            Slide 124 text

            limit anonymous functions Saturday, 5 November, 11

            Slide 125

            Slide 125 text

            limit anonymous functions $.ajax({ url: ‘/identity/crisis’, success: function(r) { // one (function(whoami) { // two alert(‘whoknows: ‘ + whoami); })(r); }, error: function(r) { // three (function(lostinspace) { // four alert(‘unknown: ‘ + lostinspace); })(r); } }); // anonymous overload! Saturday, 5 November, 11

            Slide 126

            Slide 126 text

            limit anonymous functions Saturday, 5 November, 11

            Slide 127

            Slide 127 text

            limit anonymous functions $.ajax({ url: ‘/identity/clarified’, success: whoAmI, error: lostInSpace }); // readability++ Saturday, 5 November, 11

            Slide 128

            Slide 128 text

            limit anonymous functions $.ajax({ url: ‘/identity/clarified’, success: whoAmI, error: lostInSpace }); // readability++ var whoAmI = function(identity) { alert(‘identified!: ‘ + identity); }; // testability++ var lostInSpace = function(ohnoes) { alert(‘lost!: ‘ + ohnoes); }; Saturday, 5 November, 11

            Slide 129

            Slide 129 text

            limit DOM verification Saturday, 5 November, 11

            Slide 130

            Slide 130 text

            limit DOM verification
            Saturday, 5 November, 11

            Slide 131

            Slide 131 text

            limit DOM verification
            describe(‘unnecessary verification’, function() { var $happy = $(“#happy”); expect($happy).toContain(“#and”); expect($happy).toContain(“#knows”); expect($happy).toContain(“#it”); }); // entirely unnecessary Saturday, 5 November, 11

            Slide 132

            Slide 132 text

            limit DOM verification Saturday, 5 November, 11

            Slide 133

            Slide 133 text

            limit DOM verification
              {{{a-list celebs}}} // triple curly = escape html
            Handlebars.registerHelper(‘a-list’, function(celebs) { var output; _.each(celebs, function(celeb) { output += ‘
          • ’ + celeb.name + ‘
          • ’; }); return output; }); // testable unit, acceptable Saturday, 5 November, 11

            Slide 134

            Slide 134 text

            supply structure to js heavy apps Saturday, 5 November, 11

            Slide 135

            Slide 135 text

            Saturday, 5 November, 11

            Slide 136

            Slide 136 text

            WHY DO I USE IT? Saturday, 5 November, 11

            Slide 137

            Slide 137 text

            because this is painful Saturday, 5 November, 11

            Slide 138

            Slide 138 text

            $('#something') .append('Linky') .append('Linky') .append('Button'); because this is painful Saturday, 5 November, 11

            Slide 139

            Slide 139 text

            $('#something') .append('Linky') .append('Linky') .append('Button'); because this is painful http://james.padolsey.com/javascript/jquery-code-smells/ Saturday, 5 November, 11

            Slide 140

            Slide 140 text

            WHAT DOES IT DO? Saturday, 5 November, 11

            Slide 141

            Slide 141 text

            Saturday, 5 November, 11

            Slide 142

            Slide 142 text

            MODELS Saturday, 5 November, 11

            Slide 143

            Slide 143 text

            MODELS APP.Models.User = Backbone.Model.extend({ defaults: { first: ‘Ralph’, last: ‘Wiggum’ } }); var me = new APP.Models.User({ first: ‘Dave’, last: ‘Mosher’ }); Saturday, 5 November, 11

            Slide 144

            Slide 144 text

            Saturday, 5 November, 11

            Slide 145

            Slide 145 text

            VIEWS Saturday, 5 November, 11

            Slide 146

            Slide 146 text

            VIEWS APP.Views.User = Backbone.View.extend({ el: ‘.user’, initialize: function() { this.model.bind(‘change’, this.updateUI); }, updateUI: function(model) { this.$(‘.first’).text(model.get(‘first’)); this.$(‘.last’).text(model.get(‘last’)); } }); Saturday, 5 November, 11

            Slide 147

            Slide 147 text

            VIEWS APP.Views.User = Backbone.View.extend({ el: ‘.user’, initialize: function() { this.model.bind(‘change’, this.updateUI); }, updateUI: function(model) { this.$(‘.first’).text(model.get(‘first’)); this.$(‘.last’).text(model.get(‘last’)); } }); new APP.Views.User({ model: new APP.Models.User }); me.set({first:‘Homer’, last:‘Simpson’); Saturday, 5 November, 11

            Slide 148

            Slide 148 text

            VIEWS APP.Views.User = Backbone.View.extend({ el: ‘.user’, initialize: function() { this.model.bind(‘change’, this.updateUI); }, updateUI: function(model) { this.$(‘.first’).text(model.get(‘first’)); this.$(‘.last’).text(model.get(‘last’)); } }); new APP.Views.User({ model: new APP.Models.User }); me.set({first:‘Homer’, last:‘Simpson’);
            Ralph Wiggum
            Saturday, 5 November, 11

            Slide 149

            Slide 149 text

            VIEWS APP.Views.User = Backbone.View.extend({ el: ‘.user’, initialize: function() { this.model.bind(‘change’, this.updateUI); }, updateUI: function(model) { this.$(‘.first’).text(model.get(‘first’)); this.$(‘.last’).text(model.get(‘last’)); } }); new APP.Views.User({ model: new APP.Models.User }); me.set({first:‘Homer’, last:‘Simpson’); Saturday, 5 November, 11

            Slide 150

            Slide 150 text

            VIEWS APP.Views.User = Backbone.View.extend({ el: ‘.user’, initialize: function() { this.model.bind(‘change’, this.updateUI); }, updateUI: function(model) { this.$(‘.first’).text(model.get(‘first’)); this.$(‘.last’).text(model.get(‘last’)); } }); new APP.Views.User({ model: new APP.Models.User }); me.set({first:‘Homer’, last:‘Simpson’);
            Homer Simpson
            Saturday, 5 November, 11

            Slide 151

            Slide 151 text

            Saturday, 5 November, 11

            Slide 152

            Slide 152 text

            EVENT HANDLERS Saturday, 5 November, 11

            Slide 153

            Slide 153 text

            EVENT HANDLERS document.addEventListener Saturday, 5 November, 11

            Slide 154

            Slide 154 text

            EVENT HANDLERS document.addEventListener $.click Saturday, 5 November, 11

            Slide 155

            Slide 155 text

            EVENT HANDLERS document.addEventListener $.click $.delegate ($.on/$.off for jQuery 1.7) Saturday, 5 November, 11

            Slide 156

            Slide 156 text

            EVENT HANDLERS document.addEventListener $.click $.delegate ($.on/$.off for jQuery 1.7) Backbone.View -> events: {} Saturday, 5 November, 11

            Slide 157

            Slide 157 text

            Saturday, 5 November, 11

            Slide 158

            Slide 158 text

            VIEW EVENT HANDLERS Saturday, 5 November, 11

            Slide 159

            Slide 159 text

            VIEW EVENT HANDLERS APP.myView = new (Backbone.View.extend({ el: ‘#header .auth-widget’, events: { ‘click .login’ : ‘login’, ‘click .logout’ : ‘logout’ } }))(); Saturday, 5 November, 11

            Slide 160

            Slide 160 text

            HOW DO I TEST IT? Saturday, 5 November, 11

            Slide 161

            Slide 161 text

            testing events Saturday, 5 November, 11

            Slide 162

            Slide 162 text

            testing events describe(‘myView.events’, function() { it(‘defines these events’, function() { var expected = { ‘click .login’ : ‘login’, ‘click .logout’ : ‘logout’ }; expect(APP.myView.events).toEqual(expected); }); }); Saturday, 5 November, 11

            Slide 163

            Slide 163 text

            view functions Saturday, 5 November, 11

            Slide 164

            Slide 164 text

            view functions login login: function(e) { var $node = $(e.currentTarget); var name = $node.data(‘name’); alert(‘hi, ’ + name); } Saturday, 5 November, 11

            Slide 165

            Slide 165 text

            testing view functions Saturday, 5 November, 11

            Slide 166

            Slide 166 text

            testing view functions describe(‘myView.login’, function() { it(‘says my name’, function() { spyOn(window, ‘alert’); var e = { currentTarget: $(‘’); }; myView.login(e); expect(window.alert).toHaveBeenCalledWith(‘hi, dave’); }); }); Saturday, 5 November, 11

            Slide 167

            Slide 167 text

            testing view functions describe(‘myView.login’, function() { it(‘says my name’, function() { spyOn(window, ‘alert’); var e = { currentTarget: $(‘’); }; myView.login(e); expect(window.alert).toHaveBeenCalledWith(‘hi, dave’); }); }); // arrange Saturday, 5 November, 11

            Slide 168

            Slide 168 text

            testing view functions describe(‘myView.login’, function() { it(‘says my name’, function() { spyOn(window, ‘alert’); var e = { currentTarget: $(‘’); }; myView.login(e); expect(window.alert).toHaveBeenCalledWith(‘hi, dave’); }); }); // arrange // act Saturday, 5 November, 11

            Slide 169

            Slide 169 text

            testing view functions describe(‘myView.login’, function() { it(‘says my name’, function() { spyOn(window, ‘alert’); var e = { currentTarget: $(‘’); }; myView.login(e); expect(window.alert).toHaveBeenCalledWith(‘hi, dave’); }); }); // arrange // act // assert Saturday, 5 November, 11

            Slide 170

            Slide 170 text

            routers Saturday, 5 November, 11

            Slide 171

            Slide 171 text

            routers APP.Router = new (Backbone.Router.extend({ routes: { ‘/logout/:user’ : ‘logout’ }, logout: function(user) { alert(‘bye, ‘ + user); } }))(); Saturday, 5 November, 11

            Slide 172

            Slide 172 text

            testing routes Saturday, 5 November, 11

            Slide 173

            Slide 173 text

            testing routes describe(‘APP.Router.logout’, function() { it(‘says bye’, function() { // arrange spyOn(window, ‘alert’); var router = APP.Router; // act router.logout(‘dave’); // unit router.navigate(‘/logout/dave’, true); // integration // assert expect(window.alert).toHaveBeenCalledWith(‘bye, dave’); }); }); Saturday, 5 November, 11

            Slide 174

            Slide 174 text

            models Saturday, 5 November, 11

            Slide 175

            Slide 175 text

            models APP.User = new (Backbone.Model.extend({ defaults: { name: ‘default’ }, initialize: function() { this.bind(‘change:name’, this.render); }, render: function(model, name) { alert(name); } }))(); Saturday, 5 November, 11

            Slide 176

            Slide 176 text

            testing models Saturday, 5 November, 11

            Slide 177

            Slide 177 text

            testing models describe(‘APP.User.render’, function() { it(‘says my name’, function() { // arrange spyOn(window, ‘alert’); var user = APP.User; // act user.render(jasmine.any(Object), ‘ralph’); // unit user.set({ name: ‘ralph’ }); // integration // assert expect(window.alert).toHaveBeenCalledWith(‘ralph’); }); }); Saturday, 5 November, 11

            Slide 178

            Slide 178 text

            RECAP backbone.js Saturday, 5 November, 11

            Slide 179

            Slide 179 text

            Saturday, 5 November, 11

            Slide 180

            Slide 180 text

            arrange, act, assert Saturday, 5 November, 11

            Slide 181

            Slide 181 text

            arrange, act, assert mock, and mock some more Saturday, 5 November, 11

            Slide 182

            Slide 182 text

            arrange, act, assert mock, and mock some more avoid integration tests Saturday, 5 November, 11

            Slide 183

            Slide 183 text

            TOOLS YOU SHOULD USE Saturday, 5 November, 11

            Slide 184

            Slide 184 text

            jasmine-fixture beforeEach(function(){ $container = inject('add-item'); });
            by @searls Saturday, 5 November, 11

            Slide 185

            Slide 185 text

            jasmine-stealth beforeEach(function() { someSpy = jasmine.createSpy(); someSpy.when("panda",1).thenReturn("sad"); }); it("stubs accurately", function() { expect(someSpy("panda", 1)).toBe("sad")); }); also by @searls Saturday, 5 November, 11

            Slide 186

            Slide 186 text

            jasmine-jquery var $node = inject(‘#some-id’) expect($node).toBe('div#some-id') by @velesin var $a = $(‘barcamp!’) expect($a).toHaveText('barcamp!') Saturday, 5 November, 11

            Slide 187

            Slide 187 text

            tryjasmine.com by ... @searls compiles js and coffeescript saves specs between sessions (localStorage) Saturday, 5 November, 11

            Slide 188

            Slide 188 text

            more examples? github.com/davemo/backbone-slideshow test driven backbone.js 26 specs jasmine-bdd Saturday, 5 November, 11

            Slide 189

            Slide 189 text

            acknowledgements @searls - for lots of tdd mentoring pillar technology Saturday, 5 November, 11

            Slide 190

            Slide 190 text

            WHERE CAN I LEARN? Saturday, 5 November, 11

            Slide 191

            Slide 191 text

            Tues, Nov 15 6:30pm - 8:30pm Location TBD @saskjavascript Saturday, 5 November, 11

            Slide 192

            Slide 192 text

            QUESTIONS? github.com/davemo @dmosher Saturday, 5 November, 11