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/)
wordpress高级跨屏企业主题,通用响应式跨平台站点开发,自适应PC端+各移动端屏幕设备,高级可视化自定义设置模块+高效的企业站搜索优化。wordpress绿色企业自适应主题采用标准的HTML5+CSS3语言开发,兼容当下的各种主流浏览器: IE 6+(以及类似360、遨游等基于IE内核的)、Firefox、Google Chrome、Safari、Opera等;同时支持移动终端的常用浏览器应...
ftech怎么样?ftech是一家越南本土的主机商,成立于2011年,比较低调,国内知道的人比较少。FTECH.VN以极低的成本提供高质量服务的领先提供商之一。主营虚拟主机、VPS、独立服务器、域名等传统的IDC业务,数据中心分布在河内和胡志明市。其中,VPS提供1G的共享带宽,且不限流量,还可以安装Windows server2003/2008的系统。Ftech支持信用卡、Paypal等付款,但...
Megalayer 商家主营业务是以独立服务器和站群服务器的,后来也陆续的有新增香港、菲律宾数据中心的VPS主机产品。由于其线路的丰富,还是深受一些用户喜欢的,有CN2优化直连线路,有全向国际线路,以及针对欧美的国际线路。这次有看到商家也有新增美国机房的VPS主机,也有包括15M带宽CN2优化带宽以及30M带宽的全向线路。Megalayer 商家提供的美国机房VPS产品,提供的配置方案也是比较多,...
eaccelerator为你推荐
山东省水利安全生产远程教育培训平台fugedios11SAProute回收卡巴斯基functionscss支持ipad支持ipad步骤ios特斯拉苹果5重庆宽带测速重庆市电信网速测试是哪个网站或ip
虚拟主机价格 cn域名价格 域名备案信息查询 net主机 新秒杀 t牌 l5639 512m ubuntu更新源 服务器怎么绑定域名 七夕快乐英文 cn3 网通服务器托管 网通服务器 沈阳主机托管 免费asp空间申请 中国域名 htaccess windowsserverr2 美国西雅图独立 更多