CopyrightIBMCorporation2015TrademarksMasteringMEAN:TestingtheMEANstackPage1of12MasteringMEAN:TestingtheMEANstackScottDavisJuly28,2015Takeawalkthroughthesmallpieces,looselyjoinedoftheMEANstack'stestinginfrastructure.
Noapplication,MEANorotherwise,isreadyforproductionwithoutpassingarigorous,comprehensivetestsuite.
SeehowtouseKarma,Mocha,Jasmine,andistanbul—withthehelpofPhantomJS—totesttheUGLIapp.
ViewmorecontentinthisseriesTheUserGroupListandInformation(UGLI)apphascomealongwaysinceyoustartedit.
You'restoringlocaldataintheapplicationandpullinginremotedatathroughRESTfulwebservices.
Theapplicationsportsamobile-readyresponsivewebdesign,andit'ssemanticallymarkeduptomakethemostofsearchengineoptimization(SEO).
Forauthentication,userscaneithercreatealocal,dedicatedaccountor(viaOAuth)reuseanexistingaccountstoredelsewhere.
Butyouwouldn'tfeelcomfortableputtingtheUGLIappintoproductionwithoutasolidtestingsuiteasyoursafetynet,wouldyouOfcoursenot.
Thatwouldbeprofessionallyirresponsible.
IagreewithNealFord(authorandinternationalspeaker),whocallstesting"theengineeringrigorofsoftwaredevelopment.
"WheneverIstartanengagementwithnewclients,Ilookattheirtestsuitebeforeanythingelse—eventheirdesigndocuments.
Thequality,quantity,andcomprehensivenessoftheirtestshasadirectcorrelationtothematurityoftheirsoftwaredevelopmentprocess.
Ahealthy,activelymaintainedtestsuiteisthebellwetherofaproject'soverallhealth.
Similarly,anyframeworkthatplacesapremiumontestabilitymovestothetopofmylist.
AngularJSwaswrittenbytesters,andI'mhard-pressedtothinkofanothermodernwebframeworkthat'seasiertotest.
TheMEAN.
JSstackextendstheout-of-the-boxtestabilitytoincludetestingofserver-sidelogic.
"AngularJSwaswrittenbytesters,andI'mhard-pressedtothinkofanothermodernwebframeworkthat'seasiertotest.
"Atthebeginningofthisseries,IwalkedyouthroughthebasicbuildingblocksoftheMEANstack—thesmallpieces,looselyjoinedthatmakeuptheproductioncomponentsofyourapp.
Nowit'stimetodothesameforthevariousframeworksandlibrariesyou'llusetotestyourappandmakeitproduction-ready.
I'llintroduceyoutoKarma:apluggabletestrunnerthatmakesittrivialtoruntestswritteninanytestingframeworkacrossanynumberofrealwebbrowsers(includingdeveloperWorksibm.
com/developerWorks/MasteringMEAN:TestingtheMEANstackPage2of12smartphones,tablets,andsmartTVs)andreturntheresultsinawidevarietyofformats.
Alongtheway,you'lluseJasmineforclient-sidetesting,Mochaforserver-sidetesting,andistanbulforcodecoverage.
RunningyourtestsBecauseyou'vebeenusingtheYeomangeneratorthatshipsstandardwiththeMEAN.
JSframework,youalreadyhaveseveralgeneratedtestsinplace.
Typegrunttesttorunthem.
YoushouldseeresultssimilartothoseinListing1.
Listing1.
Runningthegeneratedtests$grunttestRunning"env:test"(env)taskRunning"mochaTest:src"(mochaTest)taskApplicationloadedusingthe"test"environmentconfigurationRunning"karma:unit"(karma)taskINFO[karma]:Karmav0.
12.
31serverstartedathttp://localhost:9876/INFO[launcher]:StartingbrowserPhantomJSINFO[PhantomJS1.
9.
8(MacOSX)]:Connectedonsocket6zkU-H6qx_m2J6lY4zJ8withid51669923PhantomJS1.
9.
8(MacOSX):Executed18of18SUCCESS(0.
016secs/0.
093secs)Done,withouterrors.
Don'tbeconcernedifyouhaveerrorsorwarnings;thetestsarescaffoldedouttomatchthemodelsandcontrollersasthey'reinitiallyimplemented.
Ifyou'vebeenmakingchangestothecodeundertest(CUT)andnotupdatingthecorrespondingtests,youcanexpecterrors.
I'mthrilledeverytimeaunittestfails.
Unittestsarethecircuitbreakersofyourcodebase.
Inyourhouse,youputcircuitbreakersinbetweenthepowergridandyourexpensivepersonalelectronics.
Thatwaywhenapotentiallydamagingpowersurgecomesinoverthewire,youstandtolosea35-centcircuitbreakerinsteadofa$3,500laptop.
Similarly,everybreakingunittestisanerrorthatyouseeandyourusersdon't.
Takeamomenttofixyourbrokentestsifyoucan.
Acommonsourceoferrorsisatest'srelianceondeletedorchangedfieldnames.
Theserver-sidetestsareinapp/tests.
Theclient-sidetestsarestoredinthetestdirectoryofeachpublic/module.
Ifyoucan'timmediatelyseethesourceoftheerrorinyourtest,don'tdeletethetest;simplymoveitoutofthedirectorytreetemporarily.
Nowthatyoucanmakeacleantestrun,it'stimetodeconstructtheprocess.
UnderstandingtheGrunttesttaskAsyoutypedgrunttest,Ihopethatyouaskedyourself,"Hmm,IwonderhowGruntisrunningthosetests.
"Grunt,asyouknow,runsyourbuildscript.
Opengruntfile.
jsinyourtexteditorandscrollallthewaytothebottomofthefile.
Youcanseethetesttaskbeingregistered://Testtask.
grunt.
registerTask('test',['env:test','mochaTest','karma:unit']);ibm.
com/developerWorks/developerWorksMasteringMEAN:TestingtheMEANstackPage3of12Thefirstargumentofgrunt.
registerTaskisthenameofthetask—inthiscase,test.
Thenextargumentisanarrayofdependenttasks.
Thetesttaskfirstsetsupvaluesspecifictothetestenvironment,thenrunsalloftheserver-sidetestswritteninMocha,andfinallykicksofftheclient-sidetestsviaKarma.
Scrollupabitingruntfile.
jsuntilyoufindtheenvtask:env:{test:{NODE_ENV:'test'}},ThistaskdoeslittlemorethansettheNODE_ENVvariabletotest.
RecallthatthisvariablehelpsGruntdeterminewhichenvironment-specificsettings—inthiscase,config/env/test.
js—tomergewiththecommonsettingsinconfig/env/all.
js.
Ifyoulookatconfig/env/test.
jsinatexteditor(asshowninListing2),you'llseeacustomMongoDBconnectionstring,alongwithhooksforallofthePassportsettingsforvariousOAuthproviders:Listing2.
config/env/test.
js'usestrict';module.
exports={db:'mongodb://localhost/test-test',port:3001,app:{title:'Test-TestEnvironment'},facebook:{clientID:process.
env.
FACEBOOK_ID||'APP_ID',clientSecret:process.
env.
FACEBOOK_SECRET||'APP_SECRET',callbackURL:'http://localhost:3000/auth/facebook/callback'},google:{clientID:process.
env.
GOOGLE_ID||'APP_ID',clientSecret:process.
env.
GOOGLE_SECRET||'APP_SECRET',callbackURL:'http://localhost:3000/auth/google/callback'},//snip};ThissectionwouldbeanidealplaceforyoutopointPassporttoamockimplementationoftheMeetupauthenticationstrategy.
Thatway,youdon'tneedtorelyonhavingactualuserssetupandmakeactualOAuthrequeststoMeetup.
comduringyourtestrun.
Afterthetestenvironmentisconfigured,Gruntrunsallofyourserver-sidetestswritteninMocha.
Here'sthemochaTesttask:developerWorksibm.
com/developerWorks/MasteringMEAN:TestingtheMEANstackPage4of12mochaTest:{src:watchFiles.
mochaTests,options:{reporter:'spec',require:'server.
js'}},KnobsanddialsFormoreinformationontheknobsanddialsyoucantwistwhenrunningyourMochatests,seetheplugindocumentationforgrunt-mocha-test.
Whyaretheserver-sidetestswritteninMochainsteadofJasmineMocha'smaturity,extensibility,andpluginsmakeitoneofmyfavoritetestingframeworks.
MochaisastrongchoicefortestingthingslikeExpressroutes,controllers,andMongoDBinteraction.
AlthoughMochacaneasilyruntestsbothinNode.
jsandin-browser,theAngularJSteamprefersJasmineforin-browsertesting.
Jasmineismoreoptimizedforclient-sidetesting,sotheMEAN.
JSdeveloperstookabest-of-breedapproachandchoseastrongserver-sidetestingframeworktotesttheserverside,andastrongclient-sidetestingframeworktotesttheclientsideofthings.
Youshouldfeelcomfortableswappingouteitherorbothframeworksforthetestingtoolsofyourchoice.
Becauseserver-sidetestsare(bydefinition)notrunin-browser,theMochatestsarenotkickedoffbyKarma.
TheJasminetests—thefinalpartoftheGrunttestdependencies—aretriggeredbythekarmatask:karma:{unit:{configFile:'karma.
conf.
js'}}BeforeImoveontodeconstructingthekarma.
conf.
jsfile,openpackage.
jsoninatexteditor.
Inadditiontotheruntimemoduleslistedinthedependenciesblock,youcanseeseveralbuild-timedependencieslistedinthedevDependencies(shortfordeveloperdependencies)block.
ThisblockisspecificallywheretheGruntpluginsrelatedtoMochaandKarmaaredeclaredandinstalledwhenyoutypenpminstall:"devDependencies":{"grunt-env":"~0.
4.
1","grunt-mocha-test":"~0.
10.
0","grunt-karma":"~0.
8.
2","load-grunt-tasks":"~0.
4.
0",//snip}IntroducingKarmaKarmaistheonlytestrunnerIknowofthatisbackedupbyamaster'sthesis.
AmoresuccinctversionofthethinkingbehindKarmaistheproject'smissionstatement:Thingsshouldbesimple.
Webelieveintestingandsowewanttomakeitassimpleaspossible.
ibm.
com/developerWorks/developerWorksMasteringMEAN:TestingtheMEANstackPage5of12Andsimpleitis.
Karmaallowsyoutowriteyourtestsintheframeworkofyourchoice.
Whetheryoupreferthetest-driven-development(TDD)styleofQUnitorthebehavior-driven-development(BDD)styleofJasmine,Karmawillhappilyruntestswritteninanystyle.
(Karmaalsooffersfirst-classsupportforMochaifyouwouldprefertouseasingletestingframeworkforwritingbothserver-andclient-sidetests.
)Seasonedwebdevelopersknowhowimportantitistotesttheirappsacrossawidevarietyofbrowsers.
ThecoreJavaScriptlanguageisremarkablyconsistentacrossbrowsers,butDocumentObjectModel(DOM)manipulationandwaystomakeAjaxrequestsarefarfromstandardized.
MainstreamlibrarieslikejQueryandAngularJSdoagreatjobofpolyfillingoverbrowserincompatibilities,butthatshouldn'tlullyouintoafalsesenseofcomplacency.
Onetestisworthathousandopinions,andhavingproofthatyourappworksasintendedinaspecificbrowserisfarpreferabletosimplyassumingthatitwill.
Karmaoffersseveralpluginsthatyoucanusetolauncharealbrowserondemand,runthefulltestsuite,andthenshutdownthebrowseruponcompletion.
Thatcapabilityisconvenientforrunningthetestslocallyinthebrowserofyourchoice,butitcanbelimitingifthetestsarebeingkickedoffbyaheadlesscontinuousintegrationserversuchasJenkins,Hudson,orStrider.
Thankfully,youcanstandupalong-runningKarmaserverandcapturebrowsersonremotedevices.
CapturingabrowserisassimpleasvisitingtheURLofyourKarmaserverinthebrowser.
IfthebrowsersupportsWebSockets(caniuse.
comshowssupportineverymainstream,modernbrowser),theKarmaserverwillmaintainalong-running,durableconnectionwiththedevice.
Asnewtestsareaddedtothesuite,theKarmaserverwillserializethemacrossthewiretotheremotebrowser,runthem,andreturntheresults.
Butwhatgoodisrunningthetestsuiteifyoucan'tquantifytheresultsKarmaofferspluginsforseveraldifferentreporters.
Areportercanbeassimpleassomethingthatprintsoutadotonthecommandlineforeachpassingtest.
OrareportercanyieldfullyformattedHTML,oremitrawJUnit-compatibleXMLthatcanbetransformedintotheoutputofyourchoice.
Testingframeworks,browserlaunchers,andresultsreportersarealldefinedinthekarma.
conf.
jsfile.
Understandingkarma.
conf.
jsOpenkarma.
conf.
jsinatexteditor,asshowninListing3.
Inthefile,you'llfindclearlylabeledsettingsforframeworks,files,reporters,andbrowsers.
Listing3.
karma.
conf.
js'usestrict';/***Moduledependencies.
*/varapplicationConfiguration=require('.
/config/config');//Karmaconfigurationmodule.
exports=function(config){config.
set({developerWorksibm.
com/developerWorks/MasteringMEAN:TestingtheMEANstackPage6of12//Frameworkstouseframeworks:['jasmine'],//Listoffiles/patternstoloadinthebrowserfiles:applicationConfiguration.
assets.
lib.
js.
concat(applicationConfiguration.
assets.
js,applicationConfiguration.
assets.
tests),//Testresultsreportertouse//Possiblevalues:'dots','progress','junit','growl','coverage'//reporters:['progress'],reporters:['progress'],//Webserverportport:9876,//Enable/disablecolorsintheoutput(reportersandlogs)colors:true,//Leveloflogging//Possiblevalues:config.
LOG_DISABLE||config.
LOG_ERROR||config.
LOG_WARN||config.
LOG_INFO||config.
LOG_DEBUGlogLevel:config.
LOG_INFO,//Enable/disablewatchingfileandexecutingtestswheneveranyfilechangesautoWatch:true,//Startthesebrowsers,currentlyavailable://-Chrome//-ChromeCanary//-Firefox//-Opera//-Safari(onlyMac)//-PhantomJS//-IE(onlyWindows)browsers:['PhantomJS'],//Ifbrowserdoesnotcaptureingiventimeout[ms],killitcaptureTimeout:60000,//ContinuousIntegrationmode//Iftrue,itcapturebrowsers,runtestsandexitsingleRun:true});};Referbacktopackage.
json.
InthatfileyoucanfindcorrespondingentriesinthedevDependenciesblockforthevariousKarmaplugins:"devDependencies":{//snip"karma":"~0.
12.
0","karma-jasmine":"~0.
2.
1","karma-coverage":"~0.
2.
0","karma-chrome-launcher":"~0.
1.
2","karma-firefox-launcher":"~0.
1.
3","karma-phantomjs-launcher":"~0.
1.
2"}Becauseallofthescaffoldedclient-sidetestsarewritteninJasmine,Irecommendleavingtheframeworksarrayasitstands.
Butasyou'llseelaterinthissection,youcanfeelcomfortableaddingandremovingbrowsersatwill.
ibm.
com/developerWorks/developerWorksMasteringMEAN:TestingtheMEANstackPage7of12IntroducingPhantomJSIfyou'reawebdeveloperbutaren'tfamiliarwiththePhantomJSbrowser,you'reinforatreat.
PhantomJSisoneofawebtester'sbestfriends.
It'seasytobetrickedintothinkingofwebbrowsersasmonolithicapplicationsidentifiedbyfamiliarbrandnames:Firefox,Chrome,Safari,Opera,andInternetExplorer.
Thosebrandnamesaremerelyaconvenientwaytodescribeaspecificcollectionoftechnologiesthatincludearenderingengine(forHTMLandCSS),ascriptingengine(forJavaScript),andapluginsubsystem.
"Nowthatyou'reaseasonedMEANdeveloper,you'realreadyintimatelyfamiliarwithpluckingcomponentsoutofabrowserandrunningthemheadlessly.
Youshouldfeelrightathomerunningaheadlessrenderkitfortesting.
"Onceyourecognizebrowsersasaloosecollectionofrenderingkitsandscriptingengines,awholenewlevelofunderstandingopensup.
Forinstance,theNetscapeNavigatorbrowserhada90+percentmarketsharewhenversion2.
0wasreleasedinthemid1990s.
IEtookoverthatmarketleadjustafewyearslater.
Butinrecentyears,arenderkit—WebKit—ratherthanabrowserenjoysamajoritymarketshare.
That'sbecauseuntilrecently(seetheWebKit,meetBlinksidebar),WebKitpoweredSafari,MobileSafari,Chrome,theAndroidbrowser,theBlackBerrybrowser,Kindledevices,PlayStation,SamsungsmartTVs,LGsmartTVs,PanasonicsmartTVs,andmore.
Eventhoughtheseapplicationsanddeviceswereallassembledbydifferentcompaniesandprojects,theyshareacommonrenderkitfordisplayingHTMLandstylingitwithCSS.
WebKit,meetBlinkGooglemadenewsin2013withtheannouncementthatitwasforkingtheWebKitprojectandcreatingaseparaterenderkitnamedBlink.
Soonafter,OperaannouncedthatitwouldstopdevelopingitscustomrenderkitandadoptBlinkinstead.
(Thislistshowstheunderlyingrenderkitforallmajorbrowsers.
)Apple,whichoriginallyforkedWebKitfromtheKHTMLrenderingenginein2005,continuestoactivelydevelopandmaintaintheproject.
(SeetheWebKitentryinWikipediaformoreinformation.
)So,whatdoesthishavetodowithPhantomJSThePhantomJSwebsitetellsus:PhantomJSisaheadlessWebKitscriptablewithaJavaScriptAPI.
Aheadlessservicedoesn'trequireamonitororaGUI.
Thatsoundsperfectforrunningbrowser-basedunittestsonamonitorlesscontinuousintegrationserver,doesn'tit(TheSlimerJSprojectoffersasimilarcapability:runningaheadlessGeckorenderkittotestthepagerenderingthatoccursintheFirefoxbrowser.
)Nowthatyou'reaseasonedMEANdeveloper,you'realreadyintimatelyfamiliarwithpluckingcomponentsoutofabrowserandrunningthemheadlessly:Node.
jsisGoogleChrome'sscriptingengine(V8)runningheadlessly.
Youshouldfeelrightathomerunningaheadlessrenderkitfortesting.
developerWorksibm.
com/developerWorks/MasteringMEAN:TestingtheMEANstackPage8of12Lookingbackatkarma.
conf.
js,youcanseethatPhantomJSisinthebrowsersarray.
NowyouunderstandhowalloftheJasmineclient-sidetestscouldrunandpassinabrowserwithoutyouseeingaGUIlaunch.
ConfiguringKarmatolaunchadditionalbrowsersKarmaofferslaunchersforallmajorbrowsers.
IfyoulookbackatthedevDependenciesblockofpackage.
json,youcanseethatlaunchersarealreadyinstalledforFirefoxandChrome.
Ifyouhavethosebrowsersinstalledonyourcomputer,addthemtothebrowsersarrayinkarma.
conf.
jsandtypegrunttesttorunyourtestsuiteinthenewlyaddedbrowsers.
Iencourageyoutovisitthenpmwebsiteandsearchforkarmalaunchertoseealistofallsupportedbrowsers.
Youinstalleachlauncherandaddittopackage.
jsonbytypingnpminstallkarma-xxx-launcher--save-dev.
Oncethelauncherisinstalled,addittothebrowsersarrayinkarma.
conf.
jsandrerunyourtests.
Capturingbrowsersthatcan'tbelaunchedKarmalaunchersaretypicallyusedtolaunchbrowsersthatareco-locatedonthesamecomputer.
RecallthatKarmacanbeusedtoruntestsonremotebrowsersalso—thinksmartphones,tablets,andsmartTVs.
AnybrowserthatsupportsWebSocketscanbecapturedbyKarmaandusedasatesttarget.
Tocapturearemotebrowser,youmustfirstleavetheKarmaserverupandrunningbetweentestruns.
ToleavetheKarmaserverrunningpermanently,changethesingleRunvaluetofalseinkarma.
conf.
js://ContinuousIntegrationmode//Iftrue,itcapturebrowsers,runtestsandexitsingleRun:trueIfyourebooteithertheKarmaserveroranyofthecapturedbrowsers,they'lltrytoreconnectandrerunallofthetests.
NowthattheKarmaserverisupandrunning,visititinaremotebrowserattheURLhttp://your.
server.
ip.
address:9876.
That'sallittakestocaptureanonlaunchablebrowserusingKarma.
AddingadditionalKarmareportersNowthatyou'recomfortableaddingadditionaltestsandbrowsers,consideraddingadditionalreporterstocaptureanddisplaytheresultsofthetests.
Tostart,addthedotsreportertothereportersarrayinkarma.
conf.
js.
Thenexttimeyoutypegrunttest,you'llseeaseriesofdotsflyacrossyourscreen—oneforeverypassingtest.
Thedotsarecutebutephemeral.
Howwillyouknowhowmanytestspassedunlessyou'rewatchingthescreenastheyrunPerhapsinstallingareporterthat'sabitmoredurableisinorder.
ibm.
com/developerWorks/developerWorksMasteringMEAN:TestingtheMEANstackPage9of12Thekarma-html-reporterismostlikelywhatyou'relookingfor.
AstheexampleinFigure1shows,yougetdetailedverbalresultsforeachtest,nicelyformattedinHTML.
Figure1.
Reportgeneratedbykarma-html-reporterToinstallkarma-html-reporter,typenpminstallkarma-html-reporter--save-dev.
Thentoconfigureit,editkarma.
conf.
jslikeso:reporters:['progress','html'],htmlReporter:{outputDir:'karma_html'},Seethekarma-html-reporterpackagedetailsforthefullsetofconfigurationoptions.
IfyouwouldpreferrawXMLoutputinsteadofpolishedHTMLoutput,considerinstallingthekarma-junit-reporter.
Toinstallit,typenpminstallkarma-junit-reporter--save-dev.
Thenconfigureitinkarma.
conf.
jsasshownattheprojectsite.
Youtypedkarmalauncheratthenpmwebsitetosearchforadditionallaunchers.
YoushouldfeelequallycomfortabletypingkarmareportertofindadditionalKarmareporters.
ShowingcodecoveragewithKarmaandistanbulNotestinginfrastructureiscompletewithoutshowingtestcodecoverage.
Thepreviousreportsonlyshowedyoutheteststhatpassedandfailed—theydidn'tshowyoutheteststhatyouforgotdeveloperWorksibm.
com/developerWorks/MasteringMEAN:TestingtheMEANstackPage10of12towrite.
Agoodcode-coveragetoolshowsyouline-by-linewhichpartsofyourcodebasewerevisitedbyunittests,andmoreimportant,whichlinesofcodehaven'tbeenvisitedbyaunittestyet.
Ifyouinstallthekarma-coverageplugin(whichusestheistanbullibrary)bytypingnpminstallkarma-coverage--save-devandconfigureitbasedontheinstructions,you'llgetasetofbeautifulreportsthatdisplayeverylineofcodeinyourapplication,asinFigure2.
Figure2.
CoveragereportThegreenlineshavebeentouchedbyaunittest,andtheredlinesarethelineswaitingforafutureunittest.
MockingdependenciesAhallmarkofwell-writtenunittestsistheirindependence.
TheyshouldneverrelyonactualdatabasesormakeactualHTTPcallstolivewebservices.
Thankfully,mockingoutthesedependenciesisatime-honoredwayofrunningyourtests.
InsteadofmakingactualAjaxcallsinyourclient-sideJasminetests,considerusingthe$httpBackendmockserviceincludedwithAngularJS.
ibm.
com/developerWorks/developerWorksMasteringMEAN:TestingtheMEANstackPage11of12InsteadofrelyingonanactualMongoDBdatabasefortesting,considerusingMockgoose—apurein-memorydrop-inreplacementforMongoose(andMongoDB)writtenexpresslyfortestingpurposes.
Runningend-to-endtestswithProtractor.
jsUptothispoint,you'vebeenrunningunittests.
Unittests—bydefinition—areteststhatdon'trelyonaGUI.
Unittestsareforthenon-UIpartsofyourcodebase.
Butwhatabouttestingallofthetypingandbuttonclickingthattypicaluserswillperformwhenthey'reusingyourappTotestthattypeofbehavior,youcaninstallProtractor.
js.
TheProtractorhomepagehasafullsetofinstructionsandexamples.
Here'stheshortversion:typenpminstallprotractor--save-devtoinstallthelibrary.
Next,youwriteJasmineteststhatvisitspecificURLsandinteractwithspecificcomponentsonthepage.
Listing4showsanexampleofaProtractortestfromtheproject'shomepage.
Listing4.
AProtractortestdescribe('angularjshomepagetodolist',function(){it('shouldaddatodo',function(){browser.
get('http://www.
angularjs.
org');element(by.
model('todoText')).
sendKeys('writeaprotractortest');element(by.
css('[value="add"]')).
click();vartodoList=element.
all(by.
repeater('todointodos'));expect(todoList.
count()).
toEqual(3);expect(todoList.
get(2).
getText()).
toEqual('writeaprotractortest');});});Asyou'veprobablysurmised,thistestvisitstheAngularJShomepage,findsthetodoTextelement,typesinateststring,andclickstheaddbutton.
Thenitrunsaseriesofassertionstoensurethattheexpectedvaluesappear.
ConclusionAsIsaidearlier,andasIoftensay,onetestisworthathousandopinions.
Butcheekyrejoindersworkonlyifyoucanbackthemupwithsolidsoftwarepractices.
Ifyouputthelessonslearnedfromthisarticleintoplace,you'llbewellonyourwaytowardthe"engineeringrigor"requiredtobeapartofthisfast-paced,ever-changingsoftwareecosystem.
developerWorksibm.
com/developerWorks/MasteringMEAN:TestingtheMEANstackPage12of12RelatedtopicsAngularJSunittesting:CheckouttheunittestingsectionoftheAngularJSDeveloperGuide.
MEAN.
JStestingdocumentation:TakealookatthetestingsectionsintheMEAN.
JSdocs.
Karma:FindoutallaboutKarmaandseetheavailablepluginsforKarmaattheprojectsite.
PhantomJS:Learnmoreaboutthisscriptable,headlessbrowser.
Mocha:VisittheMochahomepagefordocumentationandexamples.
Jasmine:CheckouttheJasminedocumentation.
CopyrightIBMCorporation2015(www.
ibm.
com/legal/copytrade.
shtml)Trademarks(www.
ibm.
com/developerworks/ibm/trademarks/)
青云互联怎么样?青云互联美国洛杉矶cn2GIA云服务器低至19元/月起;香港安畅cn2云服务器低至19元/月起;日本cn2云主机低至35元/月起!青云互联是一家成立于2020年的主机服务商,致力于为用户提供高性价比稳定快速的主机托管服务。青云互联本站之前已经更新过很多相关文章介绍了,青云互联的机房有香港和洛杉矶,都有CN2 GIA线路、洛杉矶带高防,商家承诺试用7天,打死全额退款点击进入:青云互联...
美国高防服务器提速啦专业提供美国高防服务器,美国高防服务器租用,美国抗攻击服务器,高防御美国服务器租用等。我们的海外高防服务器带给您坚不可摧的DDoS防护,保障您的业务不受攻击影响。HostEase美国高防服务器位于加州和洛杉矶数据中心,均为国内访问速度最快最稳定的美国抗攻击机房,带给您快速的访问体验。我们的高防服务器配有最高层级的DDoS防护系统,每款抗攻击服务器均拥有免费DDoS防护额度,让您...
wordpress高级全行业大气外贸主题,wordpress通用全行业高级外贸企业在线询单自适应主题建站程序,完善的外贸企业建站功能模块 + 高效通用的后台自定义设置,更实用的移动设备特色功能模块 + 更适于欧美国外用户操作体验 大气简洁的网站风格设计 + 高效优化的网站程序结构,更利于Goolge等SEO搜索优化和站点收录排名。点击进入:wordpress高级全行业大气外贸主题主题价格:¥398...
eaccelerator为你推荐
设备itunes支持ipad支持ipad支持ipad城乡居民社会养老保险人脸识别生存认证iexplore.exe应用程序错误iexplore.exe---应用程序错误.是什么意思?重庆电信网速测试电信100M下载速度多少M,为什么我家里电信100M下载速度最快5M美妙,是不是严重缩水x-routerX-Router这个软件有什么用谷歌sb为什么百度一搜SB是谷歌,谷歌一搜SB是百度?icloudiphone苹果手机显示"已停用,连接itunes"是什么意思
重庆虚拟空间 虚拟主机管理软件 网游服务器租用 vps交流 中国域名交易中心 cybermonday kvmla 免费网站监控 ixwebhosting 全能主机 web服务器的架设 200g硬盘 可外链网盘 天翼云盘 上海服务器 彩虹云 国内域名 免费网络 atom处理器 空间服务器 更多