Test-Driven JavaScript Development Test-Driven JavaScript Development Christian Johansen UpperSaddleRiver,NJ • Boston • Indianapolis • SanFrancisco NewYork • Toronto • Montreal • London • Munich • Paris • Madrid Capetown • Sydney • Tokyo • Singapore • MexicoCity Manyofthedesignationsusedbymanufacturersandsellerstodistinguishtheirproductsare AcquisitionsEditor claimedastrademarks.Wherethosedesignationsappearinthisbook,andthepublisherwas TrinaMacDonald awareofatrademarkclaim,thedesignationshavebeenprintedwithinitialcapitallettersor DevelopmentEditor inallcapitals. SonglinQiu Theauthorandpublisherhavetakencareinthepreparationofthisbook,butmakeno ManagingEditor expressedorimpliedwarrantyofanykindandassumenoresponsibilityforerrorsor JohnFuller omissions.Noliabilityisassumedforincidentalorconsequentialdamagesinconnectionwith ProjectEditor orarisingoutoftheuseoftheinformationorprogramscontainedherein. MadhuBhardwaj, GlyphInternational Thepublisheroffersexcellentdiscountsonthisbookwhenorderedinquantityforbulk ProjectCoordinator purchasesorspecialsales,whichmayincludeelectronicversionsand/orcustomcoversand ElizabethRyan contentparticulartoyourbusiness,traininggoals,marketingfocus,andbrandinginterests. Formoreinformation,pleasecontact: CopyEditor MikeRead U.S.CorporateandGovernmentSales Indexer (800)382-3419 RobertSwanson [email protected] Proofreader ForsalesoutsidetheUnitedStatespleasecontact: DavidDaniels InternationalSales TechnicalReviewers [email protected] AndreaGiammarchi JoshuaGross VisitusontheWeb:informit.com/aw JacobSeidelin CoverDesigner LibraryofCongressCataloging-in-PublicationData GaryAdair Johansen,Christian,1982- Compositor Test-drivenJavaScriptdevelopment/ChristianJohansen. GlyphInternational p. cm. Includesbibliographicalreferencesandindex. ISBN-13:978-0-321-68391-5(pbk.:alk.paper) ISBN-10:0-321-68391-9(pbk.:alk.paper) 1.JavaScript(Computerprogramlanguage)I.Title. QA76.73.J39J642011 005.13’3–dc22 2010027298 Copyright(cid:2)c 2011PearsonEducation,Inc. Allrightsreserved.PrintedintheUnitedStatesofAmerica.Thispublicationisprotectedby copyright,andpermissionmustbeobtainedfromthepublisherpriortoanyprohibited reproduction,storageinaretrievalsystem,ortransmissioninanyformorbyanymeans, electronic,mechanical,photocopying,recording,orlikewise.Forinformationregarding permissions,writeto: PearsonEducation,Inc. RightsandContractsDepartment 501BoylstonStreet,Suite900 Boston,MA02116 Fax:(617)671-3447 ISBN-13:978-0-321-68391-5 ISBN-10: 0-321-68391-9 TextprintedintheUnitedStatesonrecycledpaperatRRDonnelleyinCrawfordsville, Indiana. Firstprinting,September2010 ToFrøydisandKristin,myspecialladies. This page intentionally left blank Contents Preface xix Acknowledgments xxv AbouttheAuthor xxvii PartI Test-DrivenDevelopment 1 1. AutomatedTesting 3 1.1 TheUnitTest 4 1.1.1 UnitTestingFrameworks 5 1.1.2 strftimeforJavaScriptDates 5 1.2 Assertions 9 1.2.1 RedandGreen 10 1.3 TestFunctions,Cases,andSuites 11 1.3.1 SetupandTeardown 13 1.4 IntegrationTests 14 1.5 BenefitsofUnitTests 16 1.5.1 RegressionTesting 16 1.5.2 Refactoring 17 1.5.3 Cross-BrowserTesting 17 1.5.4 OtherBenefits 17 1.6 PitfallsofUnitTesting 18 1.7 Summary 18 2. TheTest-DrivenDevelopmentProcess 21 2.1 GoalandPurposeofTest-DrivenDevelopment 21 2.1.1 TurningDevelopmentUpside-Down 22 2.1.2 DesigninTest-DrivenDevelopment 22 vii viii Contents 2.2 TheProcess 23 2.2.1 Step1:WriteaTest 24 2.2.2 Step2:WatchtheTestFail 25 2.2.3 Step3:MaketheTestPass 26 2.2.3.1 YouAin’tGonnaNeedIt 26 2.2.3.2 PassingtheTestforString.prototype.trim 27 2.2.3.3 TheSimplestSolutionthatCouldPossiblyWork 27 2.2.4 Step4:RefactortoRemoveDuplication 28 2.2.5 Lather,Rinse,Repeat 29 2.3 FacilitatingTest-DrivenDevelopment 29 2.4 BenefitsofTest-DrivenDevelopment 30 2.4.1 CodethatWorks 30 2.4.2 HonoringtheSingleResponsibilityPrinciple 30 2.4.3 ForcingConsciousDevelopment 31 2.4.4 ProductivityBoost 31 2.5 Summary 31 3. ToolsoftheTrade 33 3.1 xUnitTestFrameworks 33 3.1.1 Behavior-DrivenDevelopment 34 3.1.2 ContinuousIntegration 34 3.1.3 AsynchronousTests 35 3.1.4 FeaturesofxUnitTestFrameworks 35 3.1.4.1 TheTestRunner 35 3.1.5 Assertions 36 3.1.6 Dependencies 37 3.2 In-BrowserTestFrameworks 37 3.2.1 YUITest 38 3.2.1.1 Setup 38 3.2.1.2 RunningTests 40 3.2.2 OtherIn-BrowserTestingFrameworks 40 3.3 HeadlessTestingFrameworks 41 3.3.1 Crosscheck 42 3.3.2 Rhinoandenv.js 42 3.3.3 TheIssuewithHeadlessTestRunners 42 3.4 OneTestRunnertoRuleThemAll 42 3.4.1 HowJsTestDriverWorks 43 3.4.2 JsTestDriverDisadvantages 44 3.4.3 Setup 44 3.4.3.1 DownloadtheJarFile 44 3.4.3.2 WindowsUsers 45 3.4.3.3 StarttheServer 45 3.4.3.4 CapturingBrowsers 46 Contents ix 3.4.3.5 RunningTests 46 3.4.3.6 JsTestDriverandTDD 48 3.4.4 UsingJsTestDriverFromanIDE 49 3.4.4.1 InstallingJsTestDriverinEclipse 49 3.4.4.2 RunningJsTestDriverinEclipse 50 3.4.5 ImprovedCommandLineProductivity 51 3.4.6 Assertions 51 3.5 Summary 52 4. TesttoLearn 55 4.1 ExploringJavaScriptwithUnitTests 55 4.1.1 PitfallsofProgrammingbyObservation 58 4.1.2 TheSweetSpotforLearningTests 59 4.1.2.1 CapturingWisdomFoundintheWild 59 4.1.2.2 ExploringWeirdBehavior 59 4.1.2.3 ExploringNewBrowsers 59 4.1.2.4 ExploringFrameworks 60 4.2 PerformanceTests 60 4.2.1 BenchmarksandRelativePerformance 60 4.2.2 ProfilingandLocatingBottlenecks 68 4.3 Summary 69 PartII JavaScriptforProgrammers 71 5. Functions 73 5.1 DefiningFunctions 73 5.1.1 FunctionDeclaration 73 5.1.2 FunctionExpression 74 5.1.3 TheFunctionConstructor 75 5.2 CallingFunctions 77 5.2.1 TheargumentsObject 77 5.2.2 FormalParametersandarguments 79 5.3 ScopeandExecutionContext 80 5.3.1 ExecutionContexts 81 5.3.2 TheVariableObject 81 5.3.3 TheActivationObject 82 5.3.4 TheGlobalObject 82 5.3.5 TheScopeChain 83 5.3.6 FunctionExpressionsRevisited 84 5.4 ThethisKeyword 87 5.4.1 ImplicitlySettingthis 88 5.4.2 ExplicitlySettingthis 89 5.4.3 UsingPrimitivesAsthis 89 5.5 Summary 91 x Contents 6. AppliedFunctionsandClosures 93 6.1 BindingFunctions 93 6.1.1 Losingthis:ALightboxExample 93 6.1.2 FixingthisviaanAnonymousFunction 95 6.1.3 Function.prototype.bind 95 6.1.4 BindingwithArguments 97 6.1.5 Currying 99 6.2 ImmediatelyCalledAnonymousFunctions 101 6.2.1 AdHocScopes 101 6.2.1.1 AvoidingtheGlobalScope 101 6.2.1.2 SimulatingBlockScope 102 6.2.2 Namespaces 103 6.2.2.1 ImplementingNamespaces 104 6.2.2.2 ImportingNamespaces 106 6.3 StatefulFunctions 107 6.3.1 GeneratingUniqueIds 107 6.3.2 Iterators 109 6.4 Memoization 112 6.5 Summary 115 7. ObjectsandPrototypalInheritance 117 7.1 ObjectsandProperties 117 7.1.1 PropertyAccess 118 7.1.2 ThePrototypeChain 119 7.1.3 ExtendingObjectsthroughthePrototypeChain 121 7.1.4 EnumerableProperties 122 7.1.4.1 Object.prototype.hasOwnProperty 124 7.1.5 PropertyAttributes 126 7.1.5.1 ReadOnly 126 7.1.5.2 DontDelete 126 7.1.5.3 DontEnum 126 7.2 CreatingObjectswithConstructors 130 7.2.1 prototypeand[[Prototype]] 130 7.2.2 CreatingObjectswithnew 131 7.2.3 ConstructorPrototypes 132 7.2.3.1 AddingPropertiestothePrototype 132 7.2.4 TheProblemwithConstructors 135 7.3 Pseudo-classicalInheritance 136 7.3.1 TheInheritFunction 137 7.3.2 Accessing[[Prototype]] 138 7.3.3 Implementingsuper 139 7.3.3.1 The_superMethod 140