Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping...

47
Testing? We don’t need no stinking testing!

Transcript of Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping...

Page 1: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Testing? We don’t need no stinking testing!

Page 2: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

DEVintersectionSession AB06

Async JavaScript TestingWard Bell

[email protected]

@wardbell

Page 3: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Agenda

Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real

Page 4: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Tools

Jasmine

Angular

Karma

Web Storm

Page 5: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Jasmine 2.0 1.3

Page 6: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

jasmine matchers

Page 7: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Let’s see some tests

intro.spec.js

Page 8: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

I don’t test '3 > 4'

Page 9: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 10: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 11: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 12: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 13: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 14: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 15: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Testing and Boundaries

Browser | Bootstrap | Routing | View (html) | ViewModel | DataContext | AJAX--

web service | ORM | Database

Crossing boundaries = hi-fi + hardMinimize these crossings

Browser ------------------------------------------------------------------------------- Database

Page 16: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Test Types

Unit

Integration

End-to-end

Page 17: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

every dependency is fakedeasy to writeusually too trivial

Unit Test

A test with no real dependencies

Page 18: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Integration Test

At least one dependency is realeven if dependency uses fakesmost of the tests I write

Page 19: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

End-to-end tests (E2E)

Test the running appmimic user activity

Page 20: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

My Testing Spectrum

End-to-end testsHigh fidelityLow volume

Unit testsLow fidelityLow volume

Integration testsModest fidelityMedium volume{Us today

Page 21: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

The “runaway app”

Original

Now// move run block to'appStart'serviceapp.run( ['appStart', function ( appStart ) {

appStart.start();}]);

// dataservice autoloads data from serverapp.run( ['util', 'dataservice', function run ( util ) {

util.logger.info( "Zza SPA is loaded and running on " +util.config.server );

}]);

Page 22: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Mock the app start

appstart.spec.js

Page 23: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Controller needs data

Should show “customers” and “orders”Don’t care about the data themselves

Page 24: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Customer Controller// Customer controller state that survives// the controller's routine creation and destruction.angular.module( "app" ).value( 'customer.state', {});

// Customer controllerangular.module( "app" ).controller( 'customer',

['customer.state', 'dataservice', controller] );

function controller(customerState, dataservice) {var vm = this;vm.customerFilterText = customerState.customerFilterText || '';vm.customers = [];vm.filteredCustomers = filteredCustomers;vm.isLoadingCustomers = false;vm.isLoadingOrders = false;vm.isSelected =isSelected;vm.orderHeaders = orderHeaders;vm.select = select;vm.selectedCustomer = null;

Page 25: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Mock the dataservicefor the customer controller

customer-controller.spec.js

Page 26: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

When data-faking fails

Logic cares about object attributes

Lots of object attributes

Interrelated objects (object graphs)

takes too long to fake ‘em

Page 27: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 28: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 29: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

CustomerCustomer

OrderOrder

OrderItemOrderItem

OrderItemOptionOrderItemOption

Zza Schema

Volatile Constant

ProductProduct

ProductOptionProductOption

ProductSizeProductSize

OrderStatusOrderStatus

Page 30: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Separate two kinds of “data service”

angular.module( "app" ).factory( 'dataservice',['breeze', 'entityManagerFactory', 'lookups', 'model', 'util', factory]);

function factory( breeze, entityManagerFactory, lookups, model, util ) {var logger = util.logger,

isReady = null,// becomes a promise, not a booleanmanager = entityManagerFactory.getManager(),$timeout = util.$timeout;

var service = {cartOrder: null,draftOrder: null,getCustomers: getCustomers,getOrderHeadersForCustomer: getOrderHeadersForCustomer,lookups: lookups,ready: ready,saveChanges: saveChanges

};return service;

volatile data loaded ad hoc

Page 31: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Separate the two kinds of “data service”

angular.module( "app" ).factory( 'lookups',['breeze', 'entityManagerFactory', 'util', factory]);

function factory( breeze, emFactory, util ) {var isReady = null,// becomes a promisevar service = {

ready: ready// extended during initialization

};return service;

... extended with lookups data fetched from server ...

service.OrderStatus = ...service.products = manager.getEntities('Product');service.productOptions = manager.getEntities('ProductOption');service.productSizes = manager.getEntities('ProductSize');

lookups loaded at start

ProductProduct

ProductOptionProductOption

ProductSizeProductSize

OrderStatusOrderStatus

Page 32: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Data mother

Page 33: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Fake http traffic with $httpBackend

don’t go async until you have to

sample the traffic

replay it with $httpBackend

lookupsHttpResponse.js

Page 34: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Data mother for lookups spec

lookups.spec.js

Page 35: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Priming w/ in-mem data … in BreezeJS

don’t go async until you have to

capture data from live app

subset it

emFactoryMock

lookupsExport.jsemFactory-mock.jsemFactory-mock.spec.js

Page 36: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Data motherfor optionItems ViewModel spec

orderItemOptionVm.jsorderItemOptionVm.spec.js

Page 37: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Async for real

Page 38: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Asynchronous tests

Sources of Asynchrony DOM manipulation

setTimeout/setInterval

AJAX requests (XHR)

Pause the testrunner until test finishes

1st rule: fake it when you can

Page 39: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Angular Midway Tester

intro.angular-dodging.async.spec.jsvs

intro.ngMidwayTesting.spec.js

Page 40: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Exploring the web api w/ testswith Breeze

can the client access the server?

no need to wander through the UI

api.breeze.async.spec.js

Page 41: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Take Aways

Testing is easy; testability is hard(er) Minimize test setup Write tests you can read Write at least one test for each app js file Test async code synchronously (when you can) Dependency Injection is your friend

Page 42: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Resources

Zza sample code:https://github.com/Breeze/breeze.js.samples/tree/master/node/zza-node-mongo

jasmine: http://pivotal.github.io/jasmine/

angular: http://angularjs.org/

breeze: http://breezejs.com

PluralSight

Misko Hevery: “Code Testability”

Joe Eames: “Testing clientside JavaScript”

Elijah Manor: “Front-End First: Testing and Prototyping JavaScript Apps”

B

Page 43: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Questions?

Thank you!

Don’t forget to enter your evaluation ofAB06 Async JavaScript Testing

using EventBoard!

Page 44: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 45: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular

Promises make chained async easier

// The async pyramid of doomsomeMethod(callback1(callback2(callback3(callback4))))

What if one of the callbacks fails?

// async promise goodnesssomeMethod.then(callback1)

.then(callback2)

.then(callback3)

.then(callback4, failHandler)

“I promise to call you back … as soon as I hear”

$q // angular promises

“start spinner, get metadata, then get lookups, then get sessions, then stop spinner”

Page 46: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular
Page 47: Testing? We don’t need no stinking testing!€¦ · Basic Jasmine testing The Zza sample Stopping runaway apps Simple mock data Data mother Async for real. Tools Jasmine Angular