Your SlideShare is downloading. ×
Testable Javascript
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Testable Javascript

1,112
views

Published on

Writing testable javascript preso given at YUIConf 2011 (11/3/11) - good times!!!

Writing testable javascript preso given at YUIConf 2011 (11/3/11) - good times!!!

Published in: Business, Technology

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,112
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Enjoy writing new code, not debugging oldDebugging, fixing bugs, pulling out hair – debugging other people’s codeAs a dev what is the least favorite part of your day? Debugging / documentationWhat is the hardest part of your day? DebuggingMake life better for yourself and othersI like to code – I like to move forward & get things done – debugging in moving backwardsDebugging can suck – debugging other peoples code does 4 sure
  • Any kind of test – unit – integration - functional
  • Get manager-speak out of the wayYou have heard all of this before from industry – from manager – from co-workers - there’s a reason: less pain for you – less pain for you managers – better codeWhy everyone all up in me about these things?You probably already agree it’s a good thingmanagers NEED you to succeedSmall = testableSimple = testable – minimize side effects – side effects harder to test – harder to capture – harder to explainLoosely coupled
  • Lots of little – no bigPer function – test ONE THING AT A TIMEDo no create - injectIsolate what you want to testMocking out dependenciesCreating causes tight couplingClever comes later – if at all – don’t get cute or too clever – optimize LATERGet clever later
  • NOWDon’t have to test first – just now
  • Unit Testing = Isolating & Mocking & dealing with dependenciesYour code has dependencies you need to be aware of
  • Everyone talks about tightly vs loosely coupled – this is tightly coupled!Basic dependency injection – otherwise tight dependency couplingWhat am I actually testing? This function needed to pass z*2 to X’s flub functionI pass in a mock & an test it did the right thingTight coupling between foo() and X()
  • Basic dependency injection – static languagesWhat am I actually testing? This function needed to pass z*2 to X’s flub functionI pass in a mock & an test it did the right thing
  • Basic dependency injectionWe really see this in constructors!!! Sometimes in methodsWhat are you gonna test?? Object X hidden away
  • Constructor injection –a solution from static languages - We really see this in constructors!!! Sometimes in methodsConstruct objects with their dependencies – which can be goofy – the caller or constructor now needs to know the object’s dependencies!
  • Setter injection – which to use depends on you & api – prefer constructor – static languagesDepends also if dep is available at construction timeMaybe the setter can only used for testsConstruct objects with their dependencies
  • Debugging, fixing bugs, pulling out hairAs a dev what is the least favorite part of your day? Debugging / documentationWhat is the hardest part of your day? DebuggingYUI / Javascript lets us be smarter / not have to change our function / constructor signatures
  • Really really see it in YUI3 codeDeclare YUI3 deps & instantiate themYUI ensure something called a, b, c loaded via mods file or already thereThe load step & then tue ‘use’ stepWe just talked about this being a bad pattern – what can we do?
  • What about injection???If we inject then our CALLING function needs to know all the deps for myObjectRequires statement now gone!Should we inject???? Is this really what we want?myObject no longer self-contained
  • Now ready to test myObject!Just pushed deps up to script tags‘YUI3’ injectionIsolating objs using script tagsPre-load the mocks before the ‘real’ objects so YUI3 won’t get them
  • If we inject then our CALLING function needs to know all the deps for myObjectRequires statement now gone!Declare deps and inject!You might be tempted to do this – hopefully you don’t need to!
  • Does not have to be constructor injection!!This is better but still adds to our code – makes our code more modular however
  • A better way – isolate mocks with loaderIf you mock all of your objectsShould mock every object when you make oneOR let YUI create script tags for you using modsUse advanced loader features to inject mocks instead of the ‘real’ thing using ‘filter’ http://randomgoo.blogspot.com/
  • A better way – isolate mocks with loaderIf you mock all of your objectsShould mock every object when you make oneOR let YUI create script tags for you using modsUse advanced loader features to inject mocks instead of the ‘real’ thing using ‘filter’ http://randomgoo.blogspot.com/
  • Debugging, fixing bugs, pulling out hairAs a dev what is the least favorite part of your day? Debugging / documentationWhat is the hardest part of your day? Debugging
  • Mock object – NO DEPS!!Save as toolbar-mock.jsEVERY OBJECT SHOULD HAVE CORRESPONDING MOCK OBJECT!This is for testing DEPENDENCIES OF TOOLBAR NOT for testing toolbar itself!!
  • However you get it on the page….A is a dependency of MyObjectConstructor injectedMocked DEP NOT OBJ!
  • Debugging, fixing bugs, pulling out hairAs a dev what is the least favorite part of your day? Debugging / documentationWhat is the hardest part of your day? Debugging
  • No literally hidden!ONLY test PUBLIC functionsUse the YUI augment or plugin or other way to mix in your private stuff info the object – then they can be tested in isolation
  • ONLY TEST the PUBLIC parts of YOUR APIMENTION YUI PLUGIN AGGREGATION…Well not directlyInject them or minimize? They are a dependency black boxSince they are only used by your code – if you exercise your code you will exercise themPrivate functions are internal apiIf you got a lotta hairy ones refactor:
  • Isolate ‘window’ object or make all in a single moduleInject window object or centralize itLets you test in env w/o ‘window or a ‘complete’ window objectKRAPLOAD of stuff in ‘window’!!Want to test that we’re callingwindow.escape with the right thing – maybe can tell from return value – maybe notEsp. stuff like local storage or xmlhttprequest or websockets
  • Debugging, fixing bugs, pulling out hairAs a dev what is the least favorite part of your day? Debugging / documentationWhat is the hardest part of your day? Debugging
  • Unit testing is testing functions in isolationBut dependencies – which everything has – can be pain pointsHow about zero dependencies???Ride JS to a conclutionYUI3 is a service locatorMORE smaller modules!! Use YUI ‘use’ & composition to build them!
  • Can’t test!
  • Unit testing is testing functions in isolationBut dependencies – which everything has – can be pain pointsHow about zero dependencies???Ride JS to a conclutionYUI3 is a service locator
  • All about dep managementIdentify deps & deal with themDo not require/assume global variables – your module is a black boxAllow for headless tests
  • Debugging, fixing bugs, pulling out hairAs a dev what is the least favorite part of your day? Debugging / documentationWhat is the hardest part of your day? DebuggingWorst part debugging your codeEven worser part debugging someone else’s code – don’t be that someone else!Make life easier and better for yourself and your co-workers by having tests in place – writing simple & obvious code = testable code
  • All about dep managementIdentify deps & deal with themDo not require/assume global variables – your module is a black box
  • Transcript

    • 1. Testable Javascript MARK ETHAN TROSTLERmark@zzo.com @zzoass http://randomgoo.blogspot.com/
    • 2. “If today were the last dayof my life, would I want to do what I am about to do today?”
    • 3. KISS
    • 4. Minimize Your Pain•Write Small•Write Simple•Test Early•Test Often
    • 5. Write Small – Write Simple •Isolate code to test •Loosely couple dependencies •Be obvious •Optimize last
    • 6. Test Early – Test Often Test Now
    • 7. Explicit Dependencies
    • 8. How things can go wrong…// Call x.flub with twice zfunction foo(z) {varx = new X(); // Mmmmmtightly coupled… return x.flub(z*2);}// We want to test if x.flub was called with 14var back = foo(7);// But only have „back‟ to test! November 9, 2011
    • 9. How can we test only our code?// Call x.flub with twice zfunction foo(x, z) { return x.flub(z*2);}// Test x.flub got called with 14…varx = new MockX(),foo(x, 7);If (x.called(„flub‟).with(14)) { // a winner!!} November 9, 2011
    • 10. Really see this in constructors…// Ewww – not directly testablefunction MyObject() {this.x = new X();}MyObject.Prototpe.foo = function(z) { return this.x.flub(z*2);}var test = new MyObject(), back = test.foo(7) // cannot test what foo() did November 9, 2011
    • 11. Inject It - Constructor// Yea! Testable!function MyObject(x) {this.x = x;}MyObject.Prototpe.foo = function(z) { return this.x.flub(z*2);}varx = new MockX(), test = new MyObject(x);test.foo(7);If (x.called(„flub‟, with(14)) { // We tested only our function!} November 9, 2011
    • 12. Inject It - Setter// Yea! Testable!function MyObject() { }MyObject.prototpe.setX= function(x) {this.x = x;};MyObject.prototpe.foo = function(z) { return this.x.flub(z*2);};varx = new MockX(), test = new MyObject();test.setX(x);test.foo(7);If (x.called(„flub‟, with(14)) { // We tested only our function!} November 9, 2011
    • 13. YUI
    • 14. YUI Explicit DependenciesYUI.add(„myObject‟, function(Y) { // Code you want to testY.MyObject = function() {this.a = new Y.a();this.b = new Y.b();this.c = new Y.c(); };}, { requires: [ „a‟, „b‟, „c‟ ] });YUI.use(„myObject‟, function(Y) { new Y.MyObject(); November 9, 2011});
    • 15. Injecting YUI3 Dependencies??YUI.add(„myObject‟, function(Y) { //// Code you want to testY.MyObject = function(a, b, c) {this.a = a;this.b = b;this.c = c; };});YUI.use(„myObject‟, „a‟, „b‟, „c‟, function(Y) { // Prod new Y.MyObject(newY.a(), new Y.b(), new Y.c());});YUI.use(„myObject‟, „test‟, function(Y) { // Test new Y.MyObject(Y.Mock(), Y.Mock(), Y.Mock()); November 9, 2011});
    • 16. Isolating Dependencies<script src =“yui3.js”></script><script src =“a.mock.js”></script><script src =“b.mock.js”></script><script src =“c.mock.js”></script><script src =“myObject.js”></script><script>YUI.use(„myObject‟, function(Y) { new Y.MyObject();</script> November 9, 2011
    • 17. Injecting YUI3 DependenciesYUI.add(„myObject‟, function(Y) { //// Code you want to testY.MyObject = function(a, b, c) {this.a = a || new Y.a();this.b = b|| new Y.b();this.c = c|| new Y.c(); };}, { requires: [„a‟, „b‟, „c‟ ] });YUI.use(„myObject‟, function(Y) { // Prod new Y.MyObject();});YUI.use(„myObject‟, „test‟, function(Y) { // Test new Y.MyObject(Y.Mock(), Y.Mock(), Y.Mock());}); November 9, 2011
    • 18. Injecting YUI3 DependenciesYUI.add(„myObject‟, function(Y) { //// Code you want to testY.MyObject = function() { }Y.MyObject.prototype.setX = function(x) {this.x = x; };}, { requires: [„a‟, „b‟, „c‟ ] });YUI.use(„myObject‟, function(Y) { // Prod new Y.MyObject();});YUI.use(„myObject‟, „test‟, function(Y) { // Test new Y.MyObject().setX(Y.Mock());}); November 9, 2011
    • 19. Isolating DependenciesYUI({ modules: { a: {fullpath: ‟/a-mock.js } }}).use(test, ‟myObject, console, function( Y) {varobj = new Y.MyObject(); November 9, 2011});
    • 20. Isolating DependenciesYUI({ filter: mock:{ searchExp: “.js",replaceStr: "-mock.js" }}).use(test, ‟myObject, console, function( Y) {varobj = new Y.MyObject();}); November 9, 2011
    • 21. Mock Objects
    • 22. Mock ObjectYUI().add(‟a, function(Y) { Y.A= function() {var me = Y.Mock();Y.Mock.expect(me, { method: ”render",args: [„#toolbar‟] }); return me; }}, 1.0.0 ,{requires:[test]}); November 9, 2011
    • 23. Testing with Mocked DependenciesYUI().add(‟a, function(Y) { Y.A= function() { return Y.Mock(); };}, 1.0.0 ,{requires:[test]});YUI().use(„a‟, „test‟, „myObject‟, function(Y) {var a = new Y.A();Y.Mock.expect(a, { method: ”render",args: [„#toolbar‟] }); new MyObject(a).render(); //// verify a.render(„#toolbar‟) was called}); November 9, 2011
    • 24. Implicit Dependencies
    • 25. „Hidden‟ Dependencies Private functions are „hidden‟ dependencies Cannot test by definition! Make public? Are they part of the public API?? Mock them out?? How?? Refactor private function to be explicit dependencies Minimize their use – they cannot be tested directly Treated exactly like any other dependency November 9, 2011
    • 26. Private functionsYOU CANNOT TEST THEM! November 9, 2011
    • 27. Don‟t forget browser dependencies!YUI.add(„myObject‟, function(Y) { //// Code you want to testY.MyObject = function(window) {this.window = window; };myObject.prototype.fiddle = function(str) { return window.escape(str + „ FOOBIE‟); };});YUI.use(„myObject‟, function(Y) {varwinMock = new WindowMock(),myObj = new myObject(winMock);myObj.fiddle(„foobie‟); // Check WindowMock!!} November 9, 2011
    • 28. Recap
    • 29. Explicit DepsProblem: Public dependenciesSymptom: Explicitly declared dependenciesCure:• Eliminate tightly coupled code/use injection• Pre-load mock‟ed versions of public dependencies November 9, 2011
    • 30. Private DepsProblem: Private dependenciesSymptom: Private methods and functionsCure:• Minimize private dependencies• Make public dependency• Use composition to pull in private stuff November 9, 2011
    • 31. Browser DepsProblem: Browser dependenciesSymptom: „window‟ or global scope usageCure:• Eliminate tightly coupled code/use injection• Pre-load mock‟ed versions of public dependencies November 9, 2011
    • 32. Unit Testing Principles & PracticesAll about dependency managementIdentify dependencies and mock them outDo not take your environment for granted November 9, 2011
    • 33. “Don‟t Be Foolish”
    • 34. Resources• https://github.com/zzo/JUTE• trostler@yahoo-inc.com• @zzoass• http://randomgoo.blogspot.com/ November 9, 2011