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/)
Hostigger 主机商在前面的文章中也有介绍过几次,这个商家运营时间是有一些年份,只不过在我们圈内好像之前出现的次数不多。最近这段时间商家有提供不限流量的VPS主机,逐渐的慢慢被人认识到。在前面的介绍到他们提供的机房还是比较多的,比如土耳其、美国等。今天看到Hostigger 商家居然改动挺大的,原来蛮好的域名居然这次连带官方域名都更换掉去掉一个G(Hostiger )。估摸着这个域名也是之前...
IonSwitch是一家2016年成立的国外VPS主机商,部落上一次分享的信息还停留在2019年,主机商提供基于KVM架构的VPS产品,数据中心之前在美国西雅图,目前是美国爱达荷州科德阿伦(美国西北部,西接华盛顿州和俄勒冈州),为新建的自营数据中心。商家针对新数据中心运行及4号独立日提供了一个5折优惠码,优惠后最低1GB内存套餐每月仅1.75美元起。下面列出部分套餐配置信息。CPU:1core内存...
hostwebis怎么样?hostwebis昨天在webhosting发布了几款美国高配置大硬盘机器,但报价需要联系客服。看了下该商家的其它产品,发现几款美国服务器、法国服务器还比较实惠,100Mbps不限流量,高配置大硬盘,$44/月起,有兴趣的可以关注一下。HostWebis是一家国外主机品牌,官网宣称1998年就成立了,根据目标市场的不同,以不同品牌名称提供网络托管服务。2003年,通过与W...
eaccelerator为你推荐
投标迅雷centrescss我研制千万亿次超级电脑支持ipad尺寸(mm)操作區域手控重庆网通重庆联通网上营业厅手机版重庆宽带测速重庆云阳电信宽带测速网址谁知道,帮个忙?win10关闭445端口win10怎么关闭445的最新相关信息iphonewifi苹果手机怎么扫二维码连wifichromeframe无法安装chrome frame,求助
工信部域名备案查询 韩国vps俄罗斯美女 域名备案只选云聚达 linuxapache虚拟主机 动态域名解析软件 万网域名解析 过期已备案域名 新通用顶级域名 免费ddos防火墙 e蜗 anylink 世界测速 cn3 免费高速空间 美国堪萨斯 中国电信宽带测速网 吉林铁通 如何建立邮箱 国外视频网站有哪些 512mb 更多