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/)
4324云是成立于2012年的老牌商家,主要经营国内服务器资源,是目前国内实力很强的商家,从价格上就可以看出来商家实力,这次商家给大家带来了全网最便宜的物理服务器。只能说用叹为观止形容。官网地址 点击进入由于是活动套餐 本款产品需要联系QQ客服 购买 QQ 800083597 QQ 2772347271CPU内存硬盘带宽IP防御价格e5 2630 12核16GBSSD 500GB30M1个IP...
BuyVM测评,BuyVM怎么样?BuyVM好不好?BuyVM,2010年成立的国外老牌稳定商家,Frantech Solutions旗下,主要提供基于KVM的VPS服务器,数据中心有拉斯维加斯、纽约、卢森堡,付费可选强大的DDOS防护(月付3美金),特色是1Gbps不限流量,稳定商家,而且卢森堡不限版权。1G或以上内存可以安装Windows 2012 64bit,无需任何费用,所有型号包括免费的...
我们在去年12月分享过Hosteons新上AMD Ryzen9 3900X CPU及DDR4内存、NVMe硬盘的高性能VPS产品的消息,目前商家再次发布了产品更新信息,暂停新开100M带宽KVM套餐,新订单转而升级为新的Budget KVM VPS(SSD)系列,带宽为1Gbps端口,且配置大幅升级,目前100M带宽仅保留OpenVZ架构产品可新订购,所有原有主机不变,用户一直续费一直可用。Bud...
eaccelerator为你推荐
uctuationchrome支持ipad支持ipad支持ipad支持ipad敬请参阅报告结尾处免责声明win10445端口win7系统不能被telnet端口号,端口、服务什么全都开了127.0.0.1为什么输入127.0.0.1无法打开页面谷歌sbSb是什么意思?icloudiphone苹果6显示已停用请连接itunes什么意思
域名是什么 ftp空间 dns是什么 zpanel enzu 站群服务器 博客主机 轻博客 ibrs php空间申请 anylink 微信收钱 域名接入 上海服务器 网站在线扫描 带宽租赁 群英网络 域名转入 godaddy空间 中国电信宽带测速 更多