Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing...

437

Transcript of Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing...

Page 1: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 2: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 3: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

LearningAndroidApplicationTesting

Page 4: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TableofContents

LearningAndroidApplicationTesting

Credits

AbouttheAuthors

AbouttheReviewers

www.PacktPub.com

Supportfiles,eBooks,discountoffers,andmore

Whysubscribe?

FreeaccessforPacktaccountholders

Preface

Whatthisbookcovers

Whatyouneedforthisbook

Whothisbookisfor

Conventions

Readerfeedback

Customersupport

Downloadingtheexamplecode

Errata

Piracy

Questions

Questions

1.GettingStartedwithTesting

Why,what,how,andwhentotest?

Whattotest

Activitylifecycleevents

Databaseandfilesystemoperations

Physicalcharacteristicsofthedevice

Typesoftests

Unittests

ThesetUp()method

Page 5: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThetearDown()method

Outsidethetestmethod

Insidethetestmethod

Mockobjects

Integrationtests

UItests

Functionaloracceptancetests

Testcasescenario

Performancetests

Systemtests

AndroidStudioandotherIDEsupport

Javatestingframework

Androidtestingframework

Instrumentation

Gradle

Testtargets

CreatingtheAndroidproject

Packageexplorer

Creatingatestcase

Testannotations

Runningthetests

RunningalltestsfromAndroidStudio

RunningasingletestcasefromyourIDE

Runningfromtheemulator

Runningtestsfromthecommandline

Runningalltests

Runningtestsfromaspecifictestcase

Runningaspecifictestbyname

Runningspecifictestsbycategory

RunningtestsusingGradle

Creatingacustomannotation

Page 6: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Runningperformancetests

Dryrun

Debuggingtests

Othercommand-lineoptions

Summary

2.UnderstandingTestingwiththeAndroidSDK

Thedemonstrationapplication

Assertionsindepth

Custommessages

Staticimports

Viewassertions

Evenmoreassertions

TheTouchUtilsclass

Mockobjects

AnoverviewofMockContext

TheIsolatedContextclass

Alternateroutetofileanddatabaseoperations

TheMockContentResolverclass

TheTestCasebaseclass

Thedefaultconstructor

Thegivennameconstructor

ThesetName()method

TheAndroidTestCasebaseclass

TheassertActivityRequiresPermission()method

Description

Example

TheassertReadingContentUriRequiresPermissionmethod

Description

Example

TheassertWritingContentUriRequiresPermission()method

Description

Page 7: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Example

Instrumentation

TheActivityMonitorinnerclass

Example

TheInstrumentationTestCaseclass

ThelaunchActivityandlaunchActivityWithIntentmethods

ThesendKeysandsendRepeatedKeysmethods

TherunTestOnUiThreadhelpermethod

TheActivityTestCaseclass

ThescrubClassmethod

TheActivityInstrumentationTestCase2class

Theconstructor

ThesetUpmethod

ThetearDownmethod

TheProviderTestCase2<T>class

Theconstructor

Anexample

TheServiceTestCase<T>

Theconstructor

TheTestSuiteBuilder.FailedToCreateTestsclass

Usinglibrariesintestprojects

Summary

3.BakingwithTestingRecipes

Androidunittests

Testingactivitiesandapplications

Mockingapplicationsandpreferences

TheRenamingMockContextclass

Mockingcontexts

Testingactivities

Testingfiles,databases,andcontentproviders

TheBrowserProvidertests

Page 8: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Testingexceptions

Testinglocalandremoteservices

Extensiveuseofmockobjects

Importinglibraries

Mockitousageexample

TheEditNumberfiltertests

Testingviewsinisolation

Testingparsers

Androidassets

Theparsertest

Testingformemoryusage

TestingwithEspresso

Summary

4.ManagingYourAndroidTestingEnvironment

CreatingAndroidVirtualDevices

RunningAVDsfromthecommandline

Headlessemulator

Disablingthekeyguard

Cleaningup

Terminatingtheemulator

Additionalemulatorconfigurations

Simulatingnetworkconditions

SpeedingupyourAVDwithHAXM

AlternativestotheAVD

Runningmonkey

Theclient-servermonkey

Testscriptingwithmonkeyrunner

Gettingtestscreenshots

Recordandplayback

Summary

5.DiscoveringContinuousIntegration

Page 9: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

BuildingAndroidapplicationsmanuallyusingGradle

Git–thefastversioncontrolsystem

CreatingalocalGitrepository

ContinuousintegrationwithJenkins

InstallingandconfiguringJenkins

Creatingthejobs

ObtainingAndroidtestresults

Summary

6.PracticingTest-drivenDevelopment

GettingstartedwithTDD

Writingatestcase

Runningalltests

Refactoringthecode

AdvantagesofTDD

Understandingtherequirements

Creatingasampleproject–thetemperatureconverter

Listofrequirements

Userinterfaceconceptdesign

Creatingtheproject

CreatingaJavamodule

CreatingtheTemperatureConverterActivityTestsclass

Creatingthefixture

Creatingtheuserinterface

Testingtheexistenceoftheuserinterfacecomponents

GettingtheIDsdefined

Translatingrequirementstotests

Emptyfields

Viewproperties

Screenlayout

Addingfunctionality

Temperatureconversion

Page 10: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheEditNumberclass

TheTemperatureConverterunittests

TheEditNumbertests

TheTemperatureChangeWatcherclass

MoreTemperatureConvertertests

TheInputFiltertests

Viewingourfinalapplication

Summary

7.Behavior-drivenDevelopment

Given,When,andThen

FitNesse

RunningFitNessefromthecommandline

CreatingaTemperatureConverterTestssubwiki

Addingchildpagestothesubwiki

Addingtheacceptancetestfixture

Addingthesupportingtestclasses

GivWenZen

Creatingthetestscenario

Summary

8.TestingandProfilingPerformance

YeOldeLoggemethod

Timinglogger

PerformancetestsinAndroidSDK

Launchingtheperformancetest

CreatingtheLaunchPerformanceBaseinstrumentation

CreatingtheTemperatureConverterActivityLaunchPerformanceclass

Runningthetests

UsingtheTraceviewanddmtracedumpplatformtools

Dmtracedump

Microbenchmarks

Calipermicrobenchmarks

Page 11: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Benchmarkingthetemperatureconverter

RunningCaliper

Summary

9.AlternativeTestingTactics

Codecoverage

Jacocofeatures

Temperatureconvertercodecoverage

Generatingcodecoverageanalysisreport

Coveringtheexceptions

IntroducingRobotium

AddingRobotium

Creatingthetestcases

ThetestFahrenheitToCelsiusConversion()test

TestingbetweenActivities

Testingonthehost’sJVM

Comparingtheperformancegain

AddingAndroidtothepicture

IntroducingRobolectric

InstallingRobolectric

Addingresources

Writingsometests

Google’smarchonshadows

IntroducingFest

IntroducingSpoon

IntroducingFork

Summary

Index

Page 12: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 13: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

LearningAndroidApplicationTesting

Page 14: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 15: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

LearningAndroidApplicationTestingCopyright©2015PacktPublishing

Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.

Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthors,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.

PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.

Firstpublished:June2011

Secondedition:March2015

Productionreference:1240315

PublishedbyPacktPublishingLtd.

LiveryPlace

35LiveryStreet

BirminghamB32PB,UK.

ISBN978-1-78439-533-9

www.packtpub.com

Page 16: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 17: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreditsAuthors

PaulBlundell

DiegoTorresMilano

Reviewers

BJPeterDeLaCruz

NoureddineDimachk

MiguelLGonzalez

HenrikKirk

SérgioLima

JoãoTrindade

CommissioningEditor

TaronPereira

AcquisitionEditor

RebeccaYoué

ContentDevelopmentEditor

ManasiPandire

TechnicalEditor

IndrajitA.Das

CopyEditors

KhushnumMistry

AlfidaPaiva

VikrantPhadke

AdithiShetty

ProjectCoordinator

SuzanneCoutinho

Proofreaders

SimranBhogal

JoannaMcMahon

Indexer

HemanginiBari

Page 18: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Graphics

ValentinaD’silva

ProductionCoordinator

AlwinRoy

CoverWork

AlwinRoy

Page 19: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 20: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AbouttheAuthorsPaulBlundellisanaspiringsoftwarecraftsmanandseniorAndroiddeveloperatNovoda.BeforeNovoda,heworkedatAutoTraderandThales,withappsthathereleasedrackingupoveronemilliondownloads.Astrongbelieverinsoftwarecraftsmanship,SOLIDarchitecture,cleancode,andtesting,PaulhasusedthismethodologytosuccessfullynurtureandcreatemanyAndroidapplications.TheseincludetheTescolauncherapp,whichwaspreinstalledfortherecentlyreleasedHudl2tablet;MUBI,auniquefilmstreamingservice;andtheAutoTraderUKcarsearchapp.

Ifanyonewantstoprovidefeedback,youcanalwaystweettohim@blundell_apps.Healsolikestowrite,soyoucanfindmorematerialathttp://blog.blundellapps.com/.

I’dliketothankeveryoneatNovodaforbeinggreatguys/galsandhelpingeachotherallthetimetolearnanddevelop.Withouttheatmosphereofcraftsmanshipandconstantlearning,myskillsandthisbookwouldnothavebeenpossible.Also,I’dliketothankmygirlfriendforherendlesspatience.Everytimesheaskedmetohelpherout,I’dgivehertheexcuseofwritingmybook.Well,nomoreexcusesbecauseitisfinished!

I’dliketoacknowledgethelegacyauthorofthisbookDiegoTorresMilanofordoingagreatjob.ThechaptersoutlinedaredowntoyourinsightintotheworldoftestingonAndroid,andIhopemyrewritelivesuptoyourideals.

Finally,I’dliketothankallthepeoplewhodon’tknowmebutfromwhomI’velearntalot.Ifyou,asthereader,wantalistofotherauthorsforfurtherresearch,thisisit:KentBeck,MartinFowler,RobertCMartin,RomainGuy,RetoMeier,MarkMurphy,EricEvans,JoshuaBlock,WardCunningham,KevinRutherford,JBRainsberger,andSandroMancuso.

DiegoTorresMilanohasbeeninvolvedwiththeAndroidplatformsinceitsinception,bytheendof2007,whenhestartedexploringandresearchingtheplatform’spossibilities,mainlyintheareasofuserinterfaces,unitandacceptancetests,andTest-drivenDevelopment.

Thisisreflectedbyanumberofarticlesmainlypublishedonhispersonalblog(http://dtmilano.blogspot.com),andhisparticipationasalecturerinsomeconferencesandcourses,suchasMobileDevCamp2008inAmsterdam(Netherlands)andJapanLinuxSymposium2009(Tokyo),DroidconLondon2009,andSkillsmatter2009(London,UK).HehasalsoauthoredAndroidtrainingcoursesdeliveredtovariouscompaniesinEurope.

Previously,hewasthefounderanddeveloperofseveralopensourceprojects,mainlyCULTUniversalLinuxThinProject(http://cult-thinclient.sf.net)andtheverysuccessfulPXESUniversalLinuxThinClientproject(thatwaslateracquiredby2XSoftware,http://www.2x.com).PXESisaLinux-basedoperatingsystemspecializedforthinclients,usedbyhundredsofthousandsofthinclientsallovertheworld.Thisprojecthasapopularitypeakof35millionhitsand400KdownloadsfromSourceForgein2005.Thisprojecthadadualimpact.BigcompaniesinEuropedecidedtouseitbecauseofimprovedsecurityandefficiency;andorganizations,institutions,andschoolsinsomedevelopment

Page 21: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

countriesinSouthAmerica,Africa,andAsiadecidedtouseitbecauseoftheminimalhardwarerequirements,havingahugesocialimpactofprovidingcomputers,sometimesrecycledones,toeveryone.

AmongtheotheropensourceprojectsthathefoundedareAutoglade,Gnome-tla,andJGlade,andhehascontributedtovariousLinuxdistributions,suchasRedHat,Fedora,andUbuntu.

HehasalsogivenpresentationsattheLinuxWorld,LinuxTag,GUADECES,UniversityofBuenosAires,andsoon.

Diegohasalsodevelopedsoftware,participatedinopensourceprojects,andadvisedcompaniesworldwideformorethan15years.

Hecanbecontactedat<[email protected]>.

Page 22: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 23: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AbouttheReviewersBJPeterDeLaCruzgraduatedwithamaster’sdegreeincomputersciencefromtheUniversityofHawaiiatManoa.In2011,hebeganhiscareerasasoftwaredeveloperatReferentiaSystemsInc.inHonolulu,Hawaii.AtReferentia,heassistedinthedevelopmentoftheLiveActionproduct.AfterworkingatReferentiafor2.5years,hewashiredasaJavawebdeveloperbytheUniversityofHawaii.Betweenfall2014andspring2015semesters,heupgradedLaulima(http://laulima.hawaii.edu),thelearningmanagementsystemthattheuniversityusesfortraditionalface-to-face,online,andhybridclasses.

BJholdsthreeJavacertifications,includingtheOracleCertifiedMaster,JavaSE6Developercertification.

HeisasuccessfulAndroiddeveloper.AsofJanuary2015,hehaspublishedsevenAndroidappsonGooglePlay.Hislatestapp,ChamorroDictionary,isanexcellentlearningtoolfortheChamorrolanguage.Youcancheckouthisappsathttp://tinyurl.com/google-play-bpd.

BJreallylikesGradlebecauseitmakesbuildingapplicationsveryeasy.HewasareviewerforGradleinAction.

HishobbiesincludelearningtheJapaneselanguage,readingbooksaboutJapaneseculture,andmakingYouTubevideos.Youcancontacthimat<[email protected]>.Youcanalsovisithiswebsiteathttp://www.bjpeter.com.

IwanttothankGodforgivingmetheopportunitytoreviewthisbook.IalsowanttothankNikitaMichaelforinvitingmetobecomeareviewerandSuzanneCoutinhoforsendingallthechapterstoreview.Arigatougozaimasu!

NoureddineDimachkisapassionatevideogamersincebirth.NoureddinestartedbuildinggamesusingTheGamesFactorywhenhewasjust10yearsold.

Today,heleadsamultinationalteamof17enthusiasticdevelopersspreadacrossLebanon,Argentina,andIndiatobuildcutting-edgeapplicationsthatservemillionsofconcurrentGSMsubscribers,inadditiontomobileapplications.

Ageekbynature,Noureddinelikestoexperimentwithnewtechnologiesinhissparetime,andhe’sapassionateDota2player.

Iwouldliketothankmyamazingwifeforstandingbymeandsupportingmeinmytechnicalventures.

MiguelLGonzalezisaSpanishsoftwareengineerworkingintheUnitedKingdomsince2010.Hetookhisfirstprogrammingcourseattheearlyageofeight,andithasbeenhismainpassionandhobbysincethen.HesoonbecameattractedtotheWebandInternet,whichleadhimtostudytelecommunicationsengineering.

Hehasworkedasaresearcherintheuniversity,designingaccessiblehardwareandwirelesssensornetworks,teachingwebdevelopment,developingamixtureofJava

Page 24: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

hardware,desktops,andwebapps,andistheheadofdevelopmentinanagency.SincethetimehearrivedintheUK,hehasmainlyfocusedonwebandnativedevelopmentformobiles,andhedevelopedafewAndroidandiOSappsincoANDcoUK.In2013,hejoinedBBCtoworkoniPlayer,BBC’scatch-upservice.Itwasherethathebecamemoreseriousaboutunittesting,behavioraltesting,andhowtodrivesuccessviacontinuousintegration.

Hetriestokeepimprovinghisprojects,whichcanbefoundathttp://github.com/ktzarandmaintainhispersonalwebsite,http://mentadreams.com.SincehissonAlexwasborn,thesparetimeforsideprojectshasbeenreduced,buthiswife,Dalia,helpshimtofindtimeforthem.Nevertheless,he’slookingforwardtoplayingMonkeyIsland,designinggames,playingtheguitar,andtravelingtheworldwithhisoffspringinafewyearstime.

HenrikKirkholdsamaster’sdegreeincomputersciencefromAarhusUniversityandhasover5yearsofexperienceinAndroidapplicationdevelopment.HeiscuriousaboutnewtechnologiesandhasbeenusingScalaaswellasJavaforAndroiddevelopment.Healsoenjoysoptimizingtheuserexperiencethroughspeedandresponsivedesign.HeiscurrentlyemployedastheleaddeveloperatLapio,creatinganawesometimingandraceexperienceforathletesintheUSandEurope.Inhissparetime,heraceshismountainbike.

SérgioLimaisasoftwareengineerandanairplanepilot.It’seasytoseethathe’saveryambitiouspersonwithbroadand,atthesametime,specificinterests.HecurrentlyworksataPortuguesecompanythataimstorevolutionizetheworldwithtelecomandmobileapplications.Hiscurriculumstartedwithamaster’sdegreeinelectronicsandtelecommunicationsandhespecializedincomputerprogrammingandcomputervision.AfterworkingatsomeinstitutionsinPortugal,heworkedatCERNinSwitzerland,beforereturningtohishomecountry.

Healsolovestoflysmallplanes,suchasthePiper“Cherokee”and“Tomahawk”,fromthenearbyaerodrome,toseePortugalfromabove,admiretheradiantsceneriesofthecountry,andexperiencethefreedomofflying.

Iwouldliketothankmyfamilyandspeciallymywonderfulprincess,“Kika”,forherpatience,support,andloveduringtheprocessofreviewingthisbook.

JoãoTrindadeisasoftwaredeveloperwhospecializesindevelopingAndroidapps.

Currently,heispartofastartupinMilanthattracksyourmobilephoneusageandsuggeststhebesttariffplanforyourneeds.

HecompletedhisPhDincomputerengineeringatLisbonTechandisinterestedineverythingrelatedtomobiledevelopment,softwaretesting,dockercontainers,orcloudcomputing.

For6yearshewasaresearcherinvolvedinmultipleinternationalresearchprojectsandhaspublished18peerreviewedarticles.

Histwitterhandleris@joaotrindadeandhispersonalwebpageishttp://joaoptrindade.com.

Page 25: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

HecontributestovariousopensourceproductsonGitHub.Youcanseehisprofileathttp://github.com/joninvski.

Page 26: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 27: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

www.PacktPub.com

Page 28: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.

DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<[email protected]>formoredetails.

Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.

https://www2.packtpub.com/books/subscription/packtlib

DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt’sentirelibraryofbooks.

Page 29: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser

Page 30: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.

Page 31: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 32: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

PrefaceItdoesn’tmatterhowmuchtimeyouinvestinAndroiddesign,orevenhowcarefulyouarewhenprogramming,mistakesareinevitableandbugswillappear.ThisbookwillhelpyouminimizetheimpactoftheseerrorsinyourAndroidprojectandincreaseyourdevelopmentproductivity.Itwillshowyoutheproblemsthatareeasilyavoided,tohelpgetyouquicklytothetestingstage.

AndroidApplicationTestingGuideisthefirstandonlybookprovidingapracticalintroductiontothemostcommonlyavailabletechniques,frameworks,andtoolstoimprovethedevelopmentofyourAndroidapplications.Clear,step-by-stepinstructionsshowhowtowritetestsforyourapplicationsandassurequalitycontrolusingvariousmethodologies.

Theauthor’sexperienceinapplyingapplicationtestingtechniquestoreal-worldprojectsenableshimtoshareinsightsoncreatingprofessionalAndroidapplications.

ThebookcoversthebasicsofframeworksupportforteststoarchitecturesandtechniquessuchasTest-drivenDevelopment,whichisanagilecomponentofthesoftwaredevelopmentprocessandatechniquewhereyouwilltacklebugsearlyon.Fromthemostbasicunittestsappliedtoasampleprojecttomoresophisticatedperformancetests,thisbookprovidesadetaileddescriptionofthemostwidelyusedtechniquesintheAndroidtestingworldinarecipe-basedapproach.

Theauthorhasextensiveexperienceofworkingonvariousdevelopmentprojectsthroughouthisprofessionalcareer.AllthisresearchandknowledgehashelpedcreateabookthatwillserveasausefulresourcetoanydevelopernavigatingtheworldofAndroidtesting.

Page 33: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WhatthisbookcoversChapter1,GettingStartedwithTesting,introducesthedifferenttypesoftestingandtheirapplicabilitytosoftwaredevelopmentprojectsingeneralandtoAndroidinparticular.ItthengoesontocovertestingontheAndroidplatform,unittestingandJUnit,creatinganAndroidtestprojectandrunningtests.

Chapter2,UnderstandingTestingwiththeAndroidSDK,startsdiggingabitdeepertorecognizethebuildingblocksavailabletocreatethetests.ItcoversAssertions,TouchUtils,whichareintendedtotestuserinterfaces,mockobjects,instrumentation,andTestCaseclasshierarchies.

Chapter3,BakingwithTestingRecipes,providespracticalexamplesofdifferentsituationsyouwillcommonlyencounterwhileapplyingthedisciplinesandtechniquesdescribedbefore.Theexamplesarepresentedinacookbookstylesoyoucanadaptandusethemforyourprojects.TherecipescoverAndroidunittests,activities,applications,databasesandContentProviders,services,UIs,exceptions,parsers,memoryleaks,andalookattestingwithEspresso.

Chapter4,ManagingYourAndroidTestingEnvironment,providesdifferentconditionstorunthetests.ItstartswiththecreationoftheAndroidVirtualDevices(AVD)toprovidedifferentconditionsandconfigurationsfortheapplicationundertestandrunsthetestsusingtheavailableoptions.Finally,itintroducesmonkeyasawaytogeneratesimulatedeventsusedfortesting.

Chapter5,DiscoveringContinuousIntegration,introducesthisagiletechniqueforsoftwareengineeringandautomationthataimstoimprovethesoftwarequalityandreducethetimetakentointegratechangesbycontinuouslyapplyingintegrationandtestingfrequently.

Chapter6,PracticingTest-drivenDevelopment,introducestheTest-drivenDevelopmentdiscipline.ItstartswithageneralrevisionandlateronmovestotheconceptsandtechniquescloselyrelatedtotheAndroidplatform.Thisisacode-intensivechapter.

Chapter7,Behavior-drivenDevelopment,introducesBehavior-drivenDevelopmentandsomeconcepts,suchastheuseofacommonvocabularytoexpressthetestsandtheinclusionofbusinessparticipantsinthesoftwaredevelopmentproject.

Chapter8,TestingandProfilingPerformance,introducesaseriesofconceptsrelatedtobenchmarkingandprofilesfromtraditionalloggingstatementmethodstocreatingAndroidperformancetestsandusingprofilingtools.

Chapter9,AlternativeTestingTactics,coversaddingcodecoveragetoensureyouknowwhatistestedandwhatisn’t,aswellastestingonthehost’sJavaVirtualMachine,investigatingFest,Spoon,andthefutureofAndroidtestingtobuilduponandexpandyourAndroidtestingrange.

Page 34: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 35: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WhatyouneedforthisbookTobeabletofollowtheexamplesinthedifferentchapters,youneedacommonsetofsoftwareandtoolsinstalledandseveralothercomponentsthataredescribedineverychapterinparticular,includingtheirrespectivedownloadlocations.

Alltheexamplesarebasedonthefollowing:

MacOSX10.9.4,fullyupdatedJavaSEversion1.6.0_24(build1.6.0_24-b07)AndroidSDKtools,revision24AndroidSDKplatform-tools,revision21SDKplatformAndroid4.4,API20Androidsupportlibrary,revision21AndroidStudioIDE,Version:1.1.0Gradleversion2.2.1Gitversion1.8.5.2

Page 36: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 37: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WhothisbookisforIfyouareanAndroiddeveloperlookingtotestyourapplicationsoroptimizeyourapplicationdevelopmentprocess,thenthisbookisforyou.Nopreviousexperienceinapplicationtestingisrequired.

Page 38: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 39: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ConventionsInthisbook,youwillfindanumberofstylesoftextthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestyles,andanexplanationoftheirmeaning.

Codewordsintextareshownasfollows:“Toinvoketheamcommandwewillbeusingtheadbshellcommand”.

Ablockofcodeissetasfollows:

dependencies{

compileproject(':dummylibrary')

}

Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:

fahrenheitEditNumber

.addTextChangedListener(

newFehrenheitToCelciusWatcher(fahrenheitEditNumber,celsiusEditNumber));

}

Anycommand-lineinputoroutputiswrittenasfollows:

junit.framework.ComparisonFailure:expected:<[]>butwas:<[123.45]>

atcom.blundell.tut.EditNumberTests.testClear(EditNumberTests.java:31)

atjava.lang.reflect.Method.invokeNative(NativeMethod)

atandroid.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)

Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,inmenusordialogboxesforexample,appearinthetextlikethis:“ThefirsttestperformsaclickontheGobuttonoftheForwardingActivity.”

NoteWarningsorimportantnotesappearinaboxlikethis.

TipTipsandtricksappearlikethis.

Page 40: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 41: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.

Tosendusgeneralfeedback,simplye-mail<[email protected]>,andmentionthebook’stitleinthesubjectofyourmessage.

Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.

Page 42: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 43: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.

Page 44: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Page 45: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.

Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.

Page 46: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

PiracyPiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.

Pleasecontactusat<[email protected]>withalinktothesuspectedpiratedmaterial.

Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.

Page 47: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

QuestionsIfyouhaveaproblemwithanyaspectofthisbook,youcancontactusat<[email protected]>,andwewilldoourbesttoaddresstheproblem.

Page 48: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

QuestionsYoucancontactusat<[email protected]>ifyouarehavingaproblemwithanyaspectofthebook,andwewilldoourbesttoaddressit.

Page 49: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 50: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter1.GettingStartedwithTestingFirstly,IwillavoidintroductionstoAndroidsinceitiscoveredinmanybooksalready,andIaminclinedtobelievethatifyouarereadingabookthatcoversthismoreadvancedtopic,youwillhavealreadystartedwithAndroiddevelopment.

Iwillbereviewingthemainconceptsbehindtesting,andthetechniques,frameworks,andtoolsavailabletodeployyourtestingstrategyonAndroid.

Afterthisoverview,wecanputtheconceptslearnedintopractice.Inthischapterwewillcover:

SettinguptheinfrastructuretotestonAndroidRunningunittestsusingJUnitCreatinganAndroidinstrumentationtestprojectRunningmultipletests

WewillbecreatingasimpleAndroidprojectanditscompaniontests.Themainprojectwillbebarebonessothatyoucanconcentrateonthetestingcomponents.

IwouldsuggestthatnewdeveloperswithnoAndroidtestingexperiencereadthisbook.IfyouhavemoreexperiencewithAndroidprojectsandhavebeenusingtestingtechniquesforthem,youmightreadthischapterasarevisionorreaffirmationoftheconcepts.

Page 51: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Why,what,how,andwhentotest?Youshouldunderstandthatearlybugdetectionsavesahugeamountofprojectresourcesandreducessoftwaremaintenancecosts.Thisisthebestknownreasontowritetestsforyoursoftwaredevelopmentproject.Increasedproductivitywillsoonbeevident.

Additionally,writingtestswillgiveyouadeeperunderstandingoftherequirementsandtheproblemtobesolved.Youwillnotbeabletowritetestsforapieceofsoftwareyoudon’tunderstand.

Thisisalsothereasonbehindtheapproachofwritingteststoclearlyunderstandlegacyorthird-partycodeandhavingthetestinginfrastructuretoconfidentlychangeorupdatethecodebase.

Themorethecodeiscoveredbyyourtests,thehigherthelikelihoodofdiscoveringhiddenbugs.

If,duringthiscoverageanalysis,youfindthatsomeareasofyourcodearenotexercised,additionaltestsshouldbeaddedtocoverthiscodeaswell.

Tohelpinthisrequest,enterJacoco(http://www.eclemma.org/jacoco/),anopensourcetoolkitthatmeasuresandreportsJavacodecoverage.Itsupportsvariouscoveragetypes,asfollows:

ClassMethodBlockLine

Coveragereportscanalsobeobtainedindifferentoutputformats.JacocoissupportedtosomedegreebytheAndroidframework,anditispossibletobuildaJacocoinstrumentedversionofanAndroidapp.

WewillbeanalyzingtheuseofJacocoonAndroidtoguideustofulltestcoverageofourcodeinChapter9,AlternativeTestingTactics.

ThisscreenshotshowshowaJacococodecoveragereportisdisplayedasanHTMLfilethatshowsgreenlineswhenthecodehasbeentested:

Page 52: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Bydefault,theJacocogradlepluginisn’tsupportedinAndroidStudio;therefore,youcannotseecodecoverageinyourIDE,andsocodecoveragehastobeviewedasseparateHTMLreports.ThereareotheroptionsavailablewithotherpluginssuchasAtlassian’sCloverorEclipsewithEclEmma.

Testsshouldbeautomated,andyoushouldrunsomeoralltestseverytimeyouintroduceachangeoradditiontoyourcodeinordertoensurethatalltheconditionsthatweremetbeforearestillmet,andthatthenewcodesatisfiesthetestsasexpected.

ThisleadsustotheintroductionofContinuousIntegration,whichwillbediscussedindetailinChapter5,DiscoveringContinuousIntegration,enablingtheautomationoftestsandthebuildingprocess.

Ifyoudon’tuseautomatedtesting,itispracticallyimpossibletoadoptContinuousIntegrationaspartofthedevelopmentprocess,anditisverydifficulttoensurethatchangeswouldnotbreakexistingcode.

Havingtestsstopsyoufromintroducingnewbugsintoalreadycompletedfeatureswhenyoutouchthecodebase.Theseregressionsareeasilydone,andtestsareabarriertothishappening.Further,youcannowcatchandfindproblemsatcompiletime,thatis,whenyouaredeveloping,ratherthanreceivingthemasfeedbackwhenyourusersstartcomplaining.

Page 53: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WhattotestStrictlyspeaking,youshouldtesteverystatementinyourcode,butthisalsodependsondifferentcriteriaandcanbereducedtotestingthemainpathofexecutionorjustsomekeymethods.Usually,there’snoneedtotestsomethingthatcan’tbebroken;forexample,itusuallymakesnosensetotestgettersandsettersasyouprobablywon’tbetestingtheJavacompileronyourowncode,andthecompilerwouldhavealreadyperformeditstests.

Inadditiontoyourdomain-specificfunctionalareasthatyoushouldtest,therearesomeotherareasofanAndroidapplicationthatyoushouldconsider.Wewillbelookingattheseinthefollowingsections.

ActivitylifecycleeventsYoushouldtestwhetheryouractivitieshandlelifecycleeventscorrectly.

IfyouractivityshouldsaveitsstateduringtheonPause()oronDestroy()eventsandlaterbeabletorestoreitinonCreate(BundlesavedInstanceState),thenyoushouldbeabletoreproduceandtestalltheseconditionsandverifythatthestatewascorrectlysavedandrestored.

ConfigurationchangeeventsshouldalsobetestedassomeoftheseeventscausethecurrentActivitytoberecreated.YoushouldtestwhetherthehandlingoftheeventiscorrectandthatthenewlycreatedActivitypreservesthepreviousstate.Configurationchangesaretriggeredevenbyadevicerotation,soyoushouldtestyourapplication’sabilitytohandlethesesituations.

DatabaseandfilesystemoperationsDatabaseandfilesystemoperationsshouldbetestedtoensurethattheoperationsandanyerrorsarehandledcorrectly.Theseoperationsshouldbetestedinisolationatthelowersystemlevel,atahigherlevelthroughContentProviders,orfromtheapplicationitself.

Totestthesecomponentsinisolation,Androidprovidessomemockobjectsintheandroid.test.mockpackage.Asimplewaytothinkofamockisasadrop-inreplacementfortherealobject,whereyouhavemorecontroloftheobject’sbehavior.

PhysicalcharacteristicsofthedeviceBeforeshippingyourapplication,youshouldbesurethatallofthedifferentdevicesitcanberunonaresupported,oratleastyoushoulddetecttheunsupportedsituationandtakepertinentmeasures.

Thecharacteristicsofthedevicesthatyoushouldtestare:

NetworkcapabilitiesScreendensitiesScreenresolutionsScreensizesAvailabilityofsensorsKeyboardandotherinputdevices

Page 54: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GPSExternalstorage

Inthisrespect,anAndroidemulatorcanplayanimportantrolebecauseitispracticallyimpossibletohaveaccesstoallofthedeviceswithallofthepossiblecombinationsoffeatures,butyoucanconfigureemulatorsforalmosteverysituation.However,asmentionedbefore,leaveyourfinaltestsforactualdeviceswheretherealuserswillruntheapplicationsoyougetfeedbackfromarealenvironment.

Page 55: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 56: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TypesoftestsTestingcomesinavarietyofframeworkswithdifferinglevelsofsupportfromtheAndroidSDKandyourIDEofchoice.Fornow,wearegoingtoconcentrateonhowtotestAndroidappsusingtheinstrumentedAndroidtestingframework,whichhasfullSDKandASidesupport,andlateron,wewilldiscussthealternatives.

Testingcanbeimplementedatanytimeinthedevelopmentprocess,dependingonthetestmethodemployed.However,wewillbepromotingtestingatanearlystageofthedevelopmentcycle,evenbeforethefullsetofrequirementshasbeendefinedandthecodingprocesshasbeenstarted.

Thereareseveraltypesoftestsdependingonthecodebeingtested.Regardlessofitstype,atestshouldverifyaconditionandreturntheresultofthisevaluationasasingleBooleanvaluethatindicatesitssuccessorfailure.

Page 57: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

UnittestsUnittestsaretestswrittenbyprogrammersforotherprogrammers,andtheyshouldisolatethecomponentundertestsandbeabletotestitinarepeatableway.That’swhyunittestsandmockobjectsareusuallyplacedtogether.Youusemockobjectstoisolatetheunitfromitsdependencies,tomonitorinteractions,andalsotobeabletorepeatthetestanynumberoftimes.Forexample,ifyourtestdeletessomedatafromadatabase,youprobablydon’twantthedatatobeactuallydeletedand,therefore,notfoundthenexttimethetestisran.

JUnitisthedefactostandardforunittestsonAndroid.It’sasimpleopensourceframeworkforautomatingunittesting,originallywrittenbyErichGammaandKentBeck.

AndroidtestcasesuseJUnit3(thisisabouttochangetoJUnit4inanimpendingGooglerelease,butasofthetimeofthiswriting,weareshowingexampleswithJUnit3).Thisversiondoesn’thaveannotations,andusesintrospectiontodetectthetests.

AtypicalAndroid-instrumentedJUnittestwouldbesomethinglikethis:

publicclassMyUnitTestCaseextendsTestCase{

publicMyUnitTestCase(){

super("testSomething");

}

publicvoidtestSomething(){

fail("Testnotimplementedyet");

}

}

TipYoucandownloadtheexamplecodefilesforallPacktbooksyouhavepurchasedfromyouraccountathttp://www.packtpub.com.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Thefollowingsectionsexplainthecomponentsthatcanbeusedtobuildupatestcase.Notethatthesecomponentsandthepatternofworkingwithatestcasearenotuniquetounittests,andtheycanbedeployedfortheothertesttypesthatwewilldiscussinthefollowingsections.

ThesetUp()methodThismethodiscalledtoinitializethefixture(fixturebeingthetestanditssurroundingcodestate).

Overridingit,youhavetheopportunitytocreateobjectsandinitializefieldsthatwillbeusedbytests.It’sworthnotingthatthissetupoccursbeforeeverytest.

ThetearDown()methodThismethodiscalledtofinalizethefixture.

Page 58: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Overridingit,youcanreleaseresourcesusedbytheinitializationortests.Again,thismethodisinvokedaftereverytest.

Forexample,youcanreleaseadatabaseorcloseanetworkconnectionhere.

Therearemoremethodsyoucanhookintobeforeandafteryourtestmethods,buttheseareusedrarely,andwillbeexplainedaswebumpintothem.

OutsidethetestmethodJUnitisdesignedinawaythattheentiretreeoftestinstancesisbuiltinonepass,andthenthetestsareexecutedinasecondpass.Therefore,thetestrunnerholdsstrongreferencestoalltestinstancesforthedurationofthetestexecution.ThismeansthatforverylargeandverylongtestrunswithmanyTestinstances,noneofthetestsmaybegarbagecollecteduntiltheentiretestisrun.ThisisparticularlyimportantinAndroidandwhiletestingonlimiteddevicesassometestsmayfailnotbecauseofanintrinsicfailurebutbecauseoftheamountofmemoryneededtoruntheapplication,inadditiontoitstestsexceedingthedevicelimits.

Therefore,ifyouallocateexternalorlimitedresourcesinatest,suchasServicesorContentProviders,youareresponsibleforfreeingthoseresources.ExplicitlysettinganobjecttonullinthetearDown()method,forexample,allowsittobegarbagecollectedbeforetheendoftheentiretestrun.

InsidethetestmethodAllpublicvoidmethodswhosenamesstartwithtestwillbeconsideredasatest.AsopposedtoJUnit4,JUnit3doesn’tuseannotationstodiscoverthetests;instead,itusesintrospectiontofindtheirnames.TherearesomeannotationsavailableintheAndroidtestframeworksuchas@SmallTest,@MediumTest,or@LargeTest,whichdon’tturnasimplemethodintoatestbutorganizethemindifferentcategories.Ultimately,youwillhavetheabilitytoruntestsforasinglecategoryusingthetestrunner.

Asaruleofthumb,nameyourtestsinadescriptivewayandusenounsandtheconditionbeingtested.Also,remembertotestforexceptionsandwrongvaluesinsteadofjusttestingpositivecases.

Forexample,somevalidtestsandnamingcouldbe:

testOnCreateValuesAreLoaded()

testGivenIllegalArgumentThenAConversionErrorIsThrown()

testConvertingInputToStringIsValid()

Duringtheexecutionofthetest,someconditions,sideeffects,ormethodreturnsshouldbecomparedagainsttheexpectations.Toeasetheseoperations,JUnitprovidesafullsetofassert*methodstocomparetheexpectedresultsfromthetesttotheactualresultsafterrunningthem,throwingexceptionsiftheconditionsarenotmet.Then,thetestrunnerhandlestheseexceptionsandpresentstheresults.

Thesemethods,whichareoverloadedtosupportdifferentarguments,include:

Page 59: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

assertTrue()

assertFalse()

assertEquals()

assertNull()

assertNotNull()

assertSame()

assertNotSame()

fail()

InadditiontotheseJUnitassertmethods,AndroidextendsAssertintwospecializedclasses,providingadditionaltests:

MoreAsserts

ViewAsserts

Mockobjects

Mockobjectsaremimicobjectsusedinsteadofcallingtherealdomainobjectstoenabletestingunitsinisolation.

Generally,thisisaccomplishedtoverifythatthecorrectmethodsarecalled,buttheycanalsobeofgreathelptoisolateyourtestsfromthesurroundingcodeandbeabletorunthetestsindependentlyandensurerepeatability.

TheAndroidtestingframeworksupportsmockobjectsthatyouwillfindveryusefulwhenwritingtests.Youneedtoprovidesomedependenciestobeabletocompilethetests.Therearealsoexternallibrariesthatcanbeusedwhenmocking.

SeveralclassesareprovidedbytheAndroidtestingframeworkintheandroid.test.mockpackage:

MockApplication

MockContentProvider

MockContentResolver

MockContext

MockCursor

MockDialogInterface

MockPackageManager

MockResources

AlmostanycomponentoftheplatformthatcouldinteractwithyourActivitycanbecreatedbyinstantiatingoneoftheseclasses.

However,theyarenotrealimplementationsbutstubs,theideabeingyouextendoneoftheseclassestocreatearealmockobjectandoverridethemethodsyouwanttoimplement.AnymethodsyoudonotoverridewillthrowanUnsupportedOperationException.

Page 60: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IntegrationtestsIntegrationtestsaredesignedtotestthewayindividualcomponentsworktogether.Modulesthathavebeenunittestedindependentlyarenowcombinedtogethertotesttheintegration.

Usually,AndroidActivitiesrequiresomeintegrationwiththesysteminfrastructuretobeabletorun.TheyneedtheActivitylifecycleprovidedbytheActivityManager,andaccesstoresources,thefilesystem,anddatabases.

ThesamecriteriaapplytootherAndroidcomponentssuchasServicesorContentProvidersthatneedtointeractwithotherpartsofthesystemtoachievetheirduty.

Inallthesecases,therearespecializedtestclassesprovidedbytheAndroidtestingframeworkthatfacilitatesthecreationoftestsforthesecomponents.

UItestsUserInterfaceteststestthevisualrepresentationofyourapplication,suchashowadialoglooksorwhatUIchangesaremadewhenadialogisdismissed.

SpecialconsiderationsshouldbetakenifyourtestsinvolveUIcomponents.Asyoumayhavealreadyknown,onlythemainthreadisallowedtoaltertheUIinAndroid.Thus,aspecialannotation@UIThreadTestisusedtoindicatethataparticulartestshouldberunonthatthreadanditwouldhavetheabilitytoaltertheUI.Ontheotherhand,ifyouonlywanttorunpartsofyourtestontheUIthread,youmayusetheActivity.runOnUiThread(Runnabler)methodthatprovidesthecorrespondingRunnable,whichcontainsthetestinginstructions.

AhelperclassTouchUtilsisalsoprovidedtoaidintheUItestcreation,allowingthegenerationofthefollowingeventstosendtotheViews,suchas:

ClickDragLongclickScrollTapTouch

Bythesemeans,youcanactuallyremotecontrolyourapplicationfromthetests.Also,AndroidhasrecentlyintroducedEspressoforUIinstrumentedtests,andwewillbecoveringthisinChapter3,BakingwithTestingRecipes.

Page 61: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

FunctionaloracceptancetestsInagilesoftwaredevelopment,functionaloracceptancetestsareusuallycreatedbybusinessandQualityAssurance(QA)people,andexpressedinabusinessdomainlanguage.Thesearehigh-levelteststoassertthecompletenessandcorrectnessofauserstoryorfeature.Theyarecreatedideallythroughcollaborationbetweenbusinesscustomers,businessanalysts,QA,testers,anddevelopers.However,thebusinesscustomers(productowners)aretheprimaryownersofthesetests.

Someframeworksandtoolscanhelpinthisfield,suchasCalabash(http://calaba.sh)ormostnotablyFitNesse(http://www.fitnesse.org),whichcanbeeasilyintegrated,uptosomepoint,intotheAndroiddevelopmentprocess,andwillletyoucreateacceptancetestsandchecktheirresultsasfollows:

Page 62: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Lately,withinacceptancetesting,anewtrendnamedBehavior-drivenDevelopmenthasgainedsomepopularity,andinaverybriefdescription,itcanbeunderstoodasacousinofTest-drivenDevelopment.Itaimstoprovideacommonvocabularybetweenbusinessandtechnologypeopleinordertoincreasemutualunderstanding.

Behavior-drivenDevelopmentcanbeexpressedasaframeworkofactivitiesbasedonthreeprinciples(moreinformationcanbefoundathttp://behaviour-driven.org):

BusinessandtechnologyshouldrefertothesamesysteminthesamewayAnysystemshouldhaveanidentified,verifiablevaluetothebusinessUpfrontanalysis,design,andplanning,allhaveadiminishingreturn

Toapplytheseprinciples,businesspeopleareusuallyinvolvedinwritingtestcasescenariosinahigh-levellanguageanduseatoolsuchasjbehave(http://jbehave.org).Inthefollowingexample,thesescenariosaretranslatedintoJavacodethatexpressesthesametestscenario.

TestcasescenarioAsanillustrationofthistechnique,hereisanoversimplifiedexample.

Thescenario,aswrittenbyaproductowner,isasfollows:

GivenI'musingtheTemperatureConverter.

WhenIenter100intoCelsiusfield.

ThenIobtain212inFahrenheitfield.

Itwouldbetranslatedintosomethingsimilarto:

@Given("IamusingtheTemperatureConverter")

publicvoidcreateTemperatureConverter(){

//donothingthisissyntacticsugarforreadability

}

@When("Ienter$celsiusintoCelsiusfield")

publicvoidsetCelsius(intcelsius){

this.celsius=celsius;

}

@Then("Iobtain$fahrenheitinFahrenheitfield")

publicvoidtestCelsiusToFahrenheit(intfahrenheit){

assertEquals(fahrenheit,

TemperatureConverter.celsiusToFahrenheit(celsius));

}

Thisallowsboththeprogrammersandthebusinessuserstospeakthelanguageofthedomain(inthiscase,temperatureconversions),andbothareabletorelateitbacktotheirday-to-daywork.

Page 63: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

PerformancetestsPerformancetestsmeasureperformancecharacteristicsofthecomponentsinarepeatableway.Ifperformanceimprovementsarerequiredbysomepartoftheapplication,thebestapproachistomeasureperformancebeforeandafterachangeisintroduced.

Asiswidelyknown,prematureoptimizationdoesmoreharmthangood,soitisbettertoclearlyunderstandtheimpactofyourchangesontheoverallperformance.

TheintroductionoftheDalvikJITcompilerinAndroid2.2changedsomeoptimizationpatternsthatwerewidelyusedinAndroiddevelopment.Nowadays,everyrecommendationaboutperformanceimprovementsintheAndroiddeveloper’ssiteisbackedupbyperformancetests.

Page 64: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SystemtestsThesystemistestedasawhole,andtheinteractionbetweenthecomponents,software,andhardwareisexercised.Normally,systemtestsincludeadditionalclassesoftestssuchas:

GUItestsSmoketestsMutationtestsPerformancetestsInstallationtests

AndroidStudioandotherIDEsupportJUnitisfullysupportedbyAndroidStudio,anditletsyoucreatetestedAndroidprojects.Furthermore,youcanrunthetestsandanalyzetheresultswithoutleavingtheIDE(tosomeextent).

Thisalsoprovidesamoresubtleadvantage;beingabletorunthetestsfromtheIDEallowsyoutodebugtheteststhatarenotbehavingcorrectly.

Inthefollowingscreenshot,wecanseehowASideruns19unittests,taking1.043seconds,with0Errorsand0Failuresdetected.Thenameofeachtestanditsdurationisalsodisplayed.Iftherewereafailure,theFailureTracewouldshowtherelatedinformation,asshowninthefollowingscreenshot:

ThereisalsoAndroidsupportinEclipseIDEusingtheAndroidDevelopmentToolsplugin.

EvenifyouarenotdevelopinginanIDE,youcanfindsupporttorunthetestswithgradle(checkhttp://gradle.orgifyouarenotfamiliarwiththistool).ThetestsarerunusingthecommandgradleconnectedAndroidTest.ThiswillinstallandrunthetestsforthedebugbuildonaconnectedAndroiddevice.

ThisisactuallythesamemethodthatAndroidStudiousesunderthehood.ASidewilljustruntheGradlecommandstobuildtheprojectandrunthetests,althoughwithselective

Page 65: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

compilation.

Page 66: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 67: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

JavatestingframeworkTheJavatestingframeworkisthebackboneofAndroidtesting,andsometimes,youcangetawaywithoutwritingAndroid-specificcode.Thiscanbeagoodthing,becauseaswecontinueonourtestingquest,youwillnoticethatwedeployAndroidframeworkteststoadevice,andthishasanimpactonthespeedofourtests,thatis,thespeedwegetfeedbackfromapassorafail.

Ifyouarchitectyourappinacleverway,youcancreatepureJavaclassesthatcanbetestedinisolationawayfromAndroid.Thetwomainbenefitsofthisareincreasedspeedoffeedbackfromtestresults,andalso,toquicklyplugtogetherlibrariesandcodesnippetstocreatepowerfultestsuites,youcanusetheneartenyearsofexperienceofotherprogrammersdoingJavatesting.

Page 68: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 69: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AndroidtestingframeworkAndroidprovidesaveryadvancedtestingframeworkthatextendstheindustrystandardJUnitlibrarywithspecificfeaturesthataresuitabletoimplementallofthetestingstrategiesandtypeswementionedbefore.Insomecases,additionaltoolsareneeded,buttheintegrationofthesetoolsis,inmostofthecases,simpleandstraightforward.

MostrelevantkeyfeaturesoftheAndroidtestingenvironmentinclude:

AndroidextensionstotheJUnitframeworkthatprovideaccesstoAndroidsystemobjectsAninstrumentationframeworkthatletsthetestscontrolandexaminetheapplicationMockversionsofcommonlyusedAndroidsystemobjectsToolstorunsingletestsortestsuites,withorwithoutinstrumentationSupporttomanagetestsandtestprojectsinAndroidStudioandatthecommandline

Page 70: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

InstrumentationTheinstrumentationframeworkisthefoundationofthetestingframework.Instrumentationcontrolstheapplicationundertestsandpermitstheinjectionofmockcomponentsrequiredbytheapplicationtorun.Forexample,youcancreatemockContextsbeforetheapplicationstartsandlettheapplicationuseit.

Alltheinteractionsoftheapplicationwiththesurroundingenvironmentcanbecontrolledusingthisapproach.Youcanalsoisolateyourapplicationinarestrictedenvironmenttobeabletopredicttheresultsthatforcethevaluesreturnedbysomemethods,orthatmockpersistentandunchangeddatafortheContentProvider'sdatabasesoreventhefilesystemcontent.

AstandardAndroidprojecthasitsinstrumentationtestsinacorrelatedsourcefoldercalledandroidTest.Thiscreatesaseparateapplicationthatrunstestsonyourapplication.ThereisnoAndroidManifesthereasitisautomaticallygenerated.TheinstrumentationcanbecustomizedinsidetheAndroidclosureofyourbuild.gradlefile,andthesechangesarereflectedintheautogeneratedAndroidManifest.However,youcanstillrunyourtestswiththedefaultsettingsifyouchoosetochangenothing.

Examplesofthingsyoucanchangearethetestapplicationpackagename,yourtestrunner,orhowtotoggleperformance-testingfeatures:

testApplicationId"com.blundell.something.non.default"

testInstrumentationRunner"com.blundell.tut.CustomTestRunner"

testHandleProfilingfalse

testFunctionalTesttrue

testCoverageEnabledtrue

Here,theInstrumentationpackage(testApplicationId)isadifferentpackagetothemainapplication.Ifyoudon’tchangethisyourself,itwilldefaulttoyourmainapplicationpackagewiththe.testsuffixadded.

Then,theInstrumentationtestrunnerisdeclared,whichcanbehelpfulifyoucreatecustomannotationstoallowspecialbehavior;forexample,eachtestrunstwiceuponfailure.Inthecaseofnotdeclaringarunner,thedefaultcustomrunnerandroid.test.InstrumentationTestRunnerisused.

Atthemoment,testHandleProfilingandtestFunctionalTestareundocumentedandunused,sowatchoutforwhenwearetoldwhatwecandowiththese.SettingtestCoverageEnabledtotruewillallowyoutogathercodecoveragereportsusingJacoco.Wewillcomebacktothislater.

Also,noticethatboththeapplicationbeingtestedandtheteststhemselvesareAndroidapplicationswiththeircorrespondingAPKsinstalled.Internally,theywillbesharingthesameprocessandthushaveaccesstothesamesetoffeatures.

Whenyourunatestapplication,theActivityManager(http://developer.android.com/intl/de/reference/android/app/ActivityManager.html)usestheinstrumentationframeworktostartandcontrolthetestrunner,whichinturnuses

Page 71: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

instrumentationtoshutdownanyrunninginstancesofthemainapplication,startsthetestapplication,andthenstartsthemainapplicationinthesameprocess.Thisallowsvariousaspectsofthetestapplicationtoworkdirectlywiththemainapplication.

Page 72: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GradleGradleisanadvancedbuildtoolkitthatallowsyoutomanagedependenciesanddefineacustomlogintobuildyourproject.TheAndroidbuildsystemisapluginontopofGradle,andthisiswhatgivesyouthedomain-specificlanguagediscussedpreviouslysuchassettingatestInstrumentationRunner.

TheideaofusingGradleisthatitallowsyoutobuildyourAndroidappsfromthecommandlineformachineswithoutusinganIDEsuchasacontinuousintegrationmachine.Also,withfirstlineintegrationofGradleintothebuildingofprojectsinAndroidStudio,yougettheexactsamecustombuildconfigurationfromtheIDEorcommandline.

Otherbenefitsincludebeingabletocustomizeandextendthebuildprocess;forexample,eachtimeyourCIbuildsyourproject,youcouldautomaticallyuploadabetaAPKtotheGoogleplaystore.YoucancreatemultipleAPKswithdifferentfeaturesusingthesameproject,forexample,oneversionthattargetsGoogleplayinanapppurchaseandanotherthattargetstheAmazonappstore’scoinpayments.

GradleandtheAndroidGradlepluginmakeforapowerfulcombination,andso,wewillbeusingthisbuildframeworkthroughouttherestofthesamplesinthisbook.

Page 73: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TesttargetsDuringtheevolutionofyourdevelopmentproject,yourtestswouldbetargetedtodifferentdevices.Fromsimplicity,flexibility,andspeedoftestingonanemulatortotheunavoidablefinaltestingonthespecificdeviceyouareintendingyourapplicationtoberunupon,youshouldbeabletorunyourapplicationonallofthem.

TherearealsosomeintermediatecasessuchasrunningyourtestsonalocalJVMvirtualmachine,onthedevelopmentcomputer,oronaDalvikvirtualmachineorActivity,dependingonthecase.

Everycasehasitsprosandcons,butthegoodnewsisthatyouhaveallofthesealternativesavailabletorunyourtests.

Theemulatorisprobablythemostpowerfultargetasyoucanmodifyalmosteveryparameterfromitsconfigurationtosimulatedifferentconditionsforyourtests.Ultimately,yourapplicationshouldbeabletohandleallofthesesituations,soit’smuchbettertodiscovertheproblemsupfrontthanwhentheapplicationhasbeendelivered.

Therealdevicesarearequirementforperformancetests,asitissomewhatdifficulttoextrapolateperformancemeasurementsfromasimulateddevice.Youwillenjoytherealuserexperienceonlywhenusingtherealdevice.Rendering,scrolling,flinging,andothercasesshouldbetestedbeforedeliveringtheapplication.

Page 74: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 75: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingtheAndroidprojectWewillcreateanewAndroidproject.ThisisdonefromtheASidemenubygoingtoFile|NewProject.Thisthenleadsusthroughthewysiwygguidetocreateaproject.

Inthisparticularcase,weareusingthefollowingvaluesfortherequiredcomponentnames(clickingontheNextbuttoninbetweenscreens):

Applicationname:AndroidApplicationTestingGuideCompanydomain:blundell.comFormfactor:PhoneandTabletMinimumSDK:17AddanActivity:BlankActivity(gowithdefaultnames)

Thefollowingscreenshotshowsthestartoftheformeditorforreference:

WhenyouclickonFinishandtheapplicationiscreated,itwillautomaticallygeneratetheandroidTestsourcefolderundertheapp/srcdirectory,andthisiswhereyoucanaddyourinstrumentedtestcases.

Page 76: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TipAlternatively,tocreateanandroidTestfolderforanexistingGradleAndroidproject,youcanselectthesrcfolderandthengotoFile|New|Directory.Then,writeandroidTest/javainthedialogprompt.Whentheprojectrebuilds,thepathwillthenautomaticallybeaddedsothatyoucancreatetests.

Page 77: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

PackageexplorerAfterhavingcreatedourproject,theprojectviewshouldlooklikeoneoftheimagesshowninthefollowingscreenshot.ThisisbecauseASidehasmultiplewaystoshowtheprojectoutline.Ontheleft,wecannotetheexistenceofthetwosourcedirectories,onecoloredgreenforthetestsourceandtheotherbluefortheprojectsource.Ontheright,wehavethenewAndroidprojectviewthattriestosimplifythehierarchybycompressinguselessandmergingfunctionallysimilarfolders.

Nowthatwehavethebasicinfrastructuresetup,it’stimeforustostartaddingsometests,asshowninthefollowingscreenshot:

There’snothingtotestrightnow,butaswearesettingupthefundamentalsofaTest-drivenDevelopmentdiscipline,weareaddingadummytestjusttogetacquaintedwiththetechnique.

Thesrc/androidTest/javafolderinyourAndroidApplicationTestingGuideprojectistheperfectplacetoaddthetests.Youcoulddeclareadifferentfolderifyoureallywantedto,butwe’restickingtodefaults.Thepackageshouldbethesameasthecorrespondingpackageofthecomponentbeingtested.

Rightnow,wearenotconcentratingonthecontentofthetestsbutontheconceptsandplacementofthosetests.

Page 78: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingatestcaseAsdescribedbefore,wearecreatingourtestcasesinthesrc/androidTest/javafolderoftheproject.

Youcancreatethefilemanuallybyright-clickingonthepackageandselectingNew…|JavaClass.However,inthisparticularcase,we’lltakeadvantageofASidetocreateourJUnitTestCase.Opentheclassundertest(inthiscase,MainActivity)andhoverovertheclassnameuntilyouseealightbulb(orpressCtrl/Command+1).SelectCreateTestfromthemenuthatappears.

Thesearethevaluesthatweshouldenterwhenwecreatethetestcase:

Testinglibrary:JUnit3Classname:MainActivityTestSuperclass:junit.framework.TestCaseDestinationpackage:com.blundell.tutSuperclass:junit.framework.TestCaseGenerate:Selectnone

Afterenteringalltherequiredvalues,ourJUnittestcasecreationdialogwouldlooklikethis.

Asyoucansee,youcouldalsohavecheckedoneofthemethodsoftheclasstogenerateanemptytestmethodstub.Thesestubmethodsmaybeusefulinsomecases,butyouhavetoconsiderthattestingshouldbeabehavior-drivenprocessratherthanamethod-drivenone.

Page 79: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thebasicinfrastructureforourtestsisinplace;whatisleftistoaddadummytesttoverifythateverythingisworkingasexpected.Wenowhaveatestcasetemplate,sothenextstepistostartcompletingittosuitourneeds.Todoit,opentherecentlycreatedtestclassandaddthetestSomething()test.

Weshouldhavesomethinglikethis:

packagecom.blundell.tut;

importandroid.test.suitebuilder.annotation.SmallTest;

importjunit.framework.TestCase;

publicclassMainActivityTestextendsTestCase{

publicMainActivityTest(){

super("MainActivityTest");

}

@SmallTest

publicvoidtestSomething()throwsException{

fail("Notimplementedyet");

}

}

TipTheno-argumentconstructorisneededtorunaspecifictestfromthecommandline,asexplainedlaterusingaminstrumentation.

Page 80: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thistestwillalwaysfail,presentingthemessage:Notimplementedyet.Inordertodothis,wewillusethefailmethodfromthejunit.framework.Assertclassthatfailsthetestwiththegivenmessage.

Page 81: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestannotationsLookingcarefullyatthetestdefinition,youmightnoticethatwedecoratedthetestusingthe@SmallTestannotation,whichisawaytoorganizeorcategorizeourtestsandrunthemseparately.

Thereareotherannotationsthatcanbeusedbythetests,suchas:

Annotation Description

@SmallTest Marksatestthatshouldrunaspartofthesmalltests.

@MediumTest Marksatestthatshouldrunaspartofthemediumtests.

@LargeTest Marksatestthatshouldrunaspartofthelargetests.

@SmokeMarksatestthatshouldrunaspartofthesmoketests.Theandroid.test.suitebuilder.SmokeTestSuiteBuilderwillrunalltestswiththisannotation.

@FlakyTest

UsethisannotationontheInstrumentationTestCaseclass’testmethods.Whenthisispresent,thetestmethodisre-executedifthetestfails.Thetotalnumberofexecutionsisspecifiedbythetolerance,anddefaultsto1.Thisisusefulforteststhatmayfailduetoanexternalconditionthatcouldvarywithtime.

Forexample,tospecifyatoleranceof4,youwouldannotateyourtestwith:@FlakyTest(tolerance=4).

@UIThreadTest

UsethisannotationontheInstrumentationTestCaseclass’testmethods.Whenthisispresent,thetestmethodisexecutedontheapplication’smainthread(orUIthread).

Asinstrumentationmethodsmaynotbeusedwhenthisannotationispresent,thereareothertechniquesif,forexample,youneedtomodifytheUIandgetaccesstotheinstrumentationwithinthesametest.

Insuchcases,youcanresorttotheActivity.runOnUIThread()methodthatallowsyoutocreateanyRunnableandrunitintheUIthreadfromwithinyourtest:

mActivity.runOnUIThread(newRunnable(){

publicvoidrun(){

//dosomethings

}

});

@Suppress

Usethisannotationontestclassesortestmethodsthatshouldnotbeincludedinatestsuite.

Thisannotationcanbeusedattheclasslevel,wherenoneofthemethodsinthatclassareincludedinthetestsuite,oratthemethodlevel,toexcludejustasinglemethodorasetofmethods.

Nowthatwehavethetestsinplace,it’stimetorunthem,andthat’swhatwearegoingtodonext.

Page 82: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningthetestsThereareseveralwaysofrunningourtests,andwewillanalyzethemhere.

Additionally,asmentionedintheprevioussectionaboutannotations,testscanbegroupedorcategorizedandruntogether,dependingonthesituation.

RunningalltestsfromAndroidStudioThisisperhapsthesimplestmethodifyouhaveadoptedASideasyourdevelopmentenvironment.Thiswillrunallthetestsinthepackage.

SelecttheappmoduleinyourprojectandthengotoRun|(androidicon)AllTests.

Ifasuitabledeviceoremulatorisnotfound,youwillbeaskedtostartorconnectone.

Thetestsarethenrun,andtheresultsarepresentedinsidetheRunperspective,asshowninthefollowingscreenshot:

AmoredetailedviewoftheresultsandthemessagesproducedduringtheirexecutioncanalsobeobtainedintheLogCatviewwithintheAndroidDDMSperspective,asshowninthefollowingscreenshot:

Page 83: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningasingletestcasefromyourIDEThereisanoptiontorunasingletestcasefromASide,shouldyouneedto.Openthefilewherethetestresides,right-clickonthemethodnameyouwanttorun,andjustlikeyourunallthetests,selectRun|(androidicon)testMethodName.

Whenyourunthis,asusual,onlythistestwillbeexecuted.Inourcase,wehaveonlyonetest,sotheresultwillbesimilartothescreenshotpresentedearlier.

NoteRunningasingletestlikethisisashortcutthatactuallycreatesarunconfigurationforyouthatisspecifictothatonemethod.Ifyouwanttolookintothedetailsofthis,fromthemenu,selectRun|EditConfigurations,andunderAndroidTests,youshouldbeabletoseeaconfigurationwiththenameofthetestyoujustexecuted.

RunningfromtheemulatorThedefaultsystemimageusedbytheemulatorhastheDevToolsapplicationinstalled,providingseveralhandytoolsandsettings.Amongthesetools,wecanfindaratherlonglist,asisshowninthefollowingscreenshot:

Page 84: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Now,weareinterestedinInstrumentation,whichisthewaytorunourtests.Thisapplicationlistsallofthepackagesinstalledthatdefineinstrumentationtagtestsintheirproject.Wecanrunthetestsbyselectingourtestsbasedonthepackagename,asshowninthefollowingscreenshot:

Page 85: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Whenthetestsareruninthisway,theresultscanbeseenthroughDDMS/LogCat,asdescribedintheprevioussection.

RunningtestsfromthecommandlineFinally,testscanberunfromthecommandlinetoo.Thisisusefulifyouwanttoautomateorscripttheprocess.

Torunthetests,weusetheaminstrumentcommand(strictlyspeaking,theamcommandandinstrumentsubcommand),whichallowsustoruninstrumentationsspecifyingthepackagenameandsomeotheroptions.

Youmightwonderwhat“am”standsfor.ItisshortforActivityManager,amaincomponentoftheinternalAndroidinfrastructurethatisstartedbytheSystemServeratthebeginningofthebootprocess,anditisresponsibleformanagingActivitiesandtheirlifecycle.Additionally,aswecanseehere,itisalsoresponsibleforActivityinstrumentation.

Thegeneralusageoftheaminstrumentcommandis:

aminstrument[flags]<COMPONENT>-r-e<NAME><VALUE>-p<FILE>-w

Thistablesummarizesthemostcommonoptions:

Option Description

Page 86: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

-r Printsrawresults.Thisisusefultocollectrawperformancedata.

-e<NAME>

<VALUE>

Setsargumentsbyname.Wewillexamineitsusageshortly.Thisisagenericoptionargumentthatallowsustosetthe<name,value>pairs.

-p<FILE> Writesprofilingdatatoanexternalfile.

-wWaitsforinstrumentationtofinishbeforeexiting.Thisisnormallyusedincommands.Althoughnotmandatory,it’sveryhandy,asotherwise,youwillnotbeabletoseethetest’sresults.

Toinvoketheamcommand,wewillbeusingtheadbshellcommandor,ifyoualreadyhaveashellrunningonanemulatorordevice,youcanissuetheamcommanddirectlyintheshellcommandprompt.

RunningalltestsThiscommandlinewillopentheadbshellandthenrunalltestswiththeexceptionofperformancetests:

$:adbshell

#:aminstrument-w

com.blundell.tut.test/android.test.InstrumentationTestRunner

com.blundell.tut.MainActivityTest:

FailureintestSomething:

junit.framework.AssertionFailedError:Notimplementedyet

at

com.blundell.tut.MainActivityTest.testSomething(MainActivityTest.java:15)

atjava.lang.reflect.Method.invokeNative(NativeMethod)

atandroid.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)

atandroid.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)

atandroid.test.InstrumentationTestRunner.onStart

(InstrumentationTestRunner.java:554)

atandroid.app.Instrumentation$InstrumentationThread.run

(Instrumentation.java:1701)

TestresultsforInstrumentationTestRunner=.F

Time:0.002

FAILURES!!!

Testsrun:1,Failures:1,Errors:0

Notethatthepackageyoudeclarewith–wisthepackageofyourinstrumentationtests,notthepackageoftheapplicationundertest.

RunningtestsfromaspecifictestcaseTorunallthetestsinaspecifictestcase,youcanuse:

$:adbshell

#:aminstrument-w-eclasscom.blundell.tut.MainActivityTest

com.blundell.tut.test/android.test.InstrumentationTestRunner

Page 87: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningaspecifictestbynameAdditionally,wehavethealternativeofspecifyingwhichtestwewanttoruninthecommandline:

$:adbshell

#:aminstrument-w-eclass

com.blundell.tut.MainActivityTest\#testSomething

com.blundell.tut.test/android.test.InstrumentationTestRunner

Thistestcannotberuninthiswayunlesswehaveano-argumentconstructorinourtestcase;thatisthereasonweaddeditbefore.

RunningspecifictestsbycategoryAsmentionedbefore,testscanbegroupedintodifferentcategoriesusingannotations(TestAnnotations),andyoucanrunalltestsinthiscategory.

Thefollowingoptionscanbeaddedtothecommandline:

Option Description

-eunittrueThisrunsallunittests.TheseareteststhatarenotderivedfromInstrumentationTestCase(andarenotperformancetests).

-efunctrueThisrunsallfunctionaltests.TheseareteststhatarederivedfromInstrumentationTestCase.

-eperftrue Thisincludesperformancetests.

-esize{small|medium

|large}Thisrunssmall,medium,orlargetestsdependingontheannotationsaddedtothetests.

-eannotation

<annotation-name>

Thisrunstestsannotatedwiththisannotation.Thisoptionismutuallyexclusivewiththesizeoption.

Inourexample,weannotatedthetestmethodtestSomething()[email protected],andisthusruneventuallywithotherteststhatbelongtothatsamecategory,whenwespecifythetestsizeassmall.

Thiscommandlinewillrunallthetestsannotatedwith@SmallTest:

$:adbshell

#:aminstrument-w-esizesmall

com.blundell.tut.test/android.test.InstrumentationTestRunner

RunningtestsusingGradleYourgradlebuildscriptcanalsohelpyourunthetestsandthiswillactuallydothepreviouscommandsunderthehood.Gradlecanrunyourtestswiththiscommand:

gradleconnectedAndroidTest

Creatingacustomannotation

Incaseyoudecidetosortthetestsbyacriterionotherthantheirsize,acustomannotation

Page 88: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

canbecreatedandthenspecifiedinthecommandline.

Asanexample,let’ssaywewanttoarrangeourtestsaccordingtotheirimportance,sowecreateanannotation@VeryImportantTest,whichwewilluseinanyclasswherewewritetests(MainActivityTestforexample):

packagecom.blundell.tut;

/**

*Markerinterfacetosegregateimportanttests

*/

@Retention(RetentionPolicy.RUNTIME)

public@interfaceVeryImportantTest{

}

Followingthis,wecancreateanothertestandannotateitwith@VeryImportantTest:

@VeryImportantTest

publicvoidtestOtherStuff(){

fail("Alsonotimplementedyet");

}

So,aswementionedbefore,wecanincludethisannotationintheaminstrumentcommandlinetorunonlytheannotatedtests:

$:adbshell

#:aminstrument-w-eannotationcom.blundell.tut.VeryImportantTest

com.blundell.tut.test/android.test.InstrumentationTestRunner

Runningperformancetests

WewillbereviewingperformancetestdetailsinChapter8,TestingandProfilingPerformance,buthere,wewillintroducetheavailableoptionstotheaminstrumentcommand.

Toincludeperformancetestsonyourtestrun,youshouldaddthiscommandlineoption:

-eperftrue:Thisincludesperformancetests

Dryrun

Sometimes,youmightonlyneedtoknowwhattestswillberuninsteadofactuallyrunningthem.

Thisistheoptionyouneedtoaddtoyourcommandline:

-elogtrue:Thisdisplaystheteststoberuninsteadofrunningthem

Thisisusefulifyouarewritingscriptsaroundyourtestsorperhapsbuildingothertools.

Page 89: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

DebuggingtestsYoushouldassumethatyourtestsmighthavebugstoo.Insuchacase,usualdebuggingtechniquesapply,forexample,addingmessagesthroughLogCat.

Ifamoresophisticateddebuggingtechniqueisneeded,youshouldattachthedebuggertothetestrunner.

InordertodothiswithoutgivingupontheconvenienceoftheIDEandnothavingtorememberhard-to-memorizecommand-lineoptions,youcanDebugRunyourrunconfigurations.Thus,youcansetabreakpointinyourtestsanduseit.Totoggleabreakpoint,youcanselectthedesiredlineintheeditorandleft-clickonthemargin.

Onceitisdone,youwillbeinastandarddebuggingsession,andthedebugwindowshouldbeavailabletoyou.

Itisalsopossibletodebugyourtestsfromthecommandline;youcanusecodeinstructionstowaitforyourdebuggertoattach.Wewon’tbeusingthiscommand;ifyouwantmoredetails,theycanbefoundat(http://developer.android.com/reference/android/test/InstrumentationTestRunner.html).

Page 90: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Othercommand-lineoptionsTheaminstrumentcommandacceptsother<name,value>pairsbesidethepreviouslymentionedones:

Name Value

debug true.Setbreakpointsinyourcode.

package Thisisafullyqualifiedpackagenameofoneorseveralpackagesinthetestapplication.

classAfullyqualifiedtestcaseclasstobeexecutedbythetestrunner.Optionally,thiscouldincludethetestmethodnameseparatedfromtheclassnamebyahash(#).

coverage

true.RunstheEMMAcodecoverageandwritestheoutputtoafilethatcanalsobespecified.WewilldigintothedetailsaboutsupportingEMMAcodecoverageforourtestsinChapter9,AlternativeTestingTactics.

Page 91: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 92: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryWehavereviewedthemaintechniquesandtoolsbehindtestingonAndroid.Havingacquiredthisknowledge,itwillletusbeginourjourneysothatwecanstartexploitingthebenefitsoftestinginoursoftwaredevelopmentprojects.

Sofar,wehavevisitedthefollowingsubjects:

Webrieflyanalyzedthewhys,whats,hows,andwhensoftesting.Henceforth,wewillconcentratemoreonexploringthehows,nowthatyou’regivingtestingtheimportanceitdeserves.Weenumeratedthedifferentandmostcommontypesoftestsyouwouldneedinyourprojects,describedsomeofthetoolswecancountonourtestingtoolbox,andprovidedanintroductoryexampleofaJUnitunittesttobetterunderstandwhatwearediscussing.WealsocreatedourfirstAndroidprojectwithtests,usingtheAndroidStudioIDEandGradle.WealsocreatedasimpletestclasstotesttheActivityinourproject.Wehaven’taddedanyusefultestcasesyet,butaddingthosesimpleoneswasintendedtovalidateourinfrastructure.WealsoranthissimpletestfromourIDEandfromthecommandlinetounderstandthealternativeswehave.Inthisprocess,wementionedtheActivityManageranditscommandlineincarnationam.Wecreatedacustomannotationtosortourtestsanddemonstratehowwecanseparateordifferentiatesuitesoftests.

Inthenextchapter,wewillstartanalyzingthementionedtechniques,frameworks,andtoolsinmuchgreaterdetail,andprovideexamplesoftheirusage.

Page 93: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 94: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter2.UnderstandingTestingwiththeAndroidSDKWenowknowhowtocreatetestsinsideanAndroidprojectandhowtorunthesetests.Itisnowtimetostartdiggingabitdeepertorecognizethebuildingblocksavailabletocreatemoreusefultests.

Inthissecondchapter,wewillbecoveringthefollowingtopics:

CommonassertionsViewassertionsOtherassertiontypesHelperstotestUserInterfacesMockobjectsInstrumentationTestCaseclasshierarchiesUsingexternallibraries

Wewillbeanalyzingthesecomponentsandshowingexamplesoftheirusewhenapplicable.TheexamplesinthischapterareintentionallysplitfromtheoriginalAndroidprojectthatcontainsthem.Thisisdonetoletyouconcentrateandfocusonlyonthesubjectbeingpresented,thoughthecompleteexamplesinasingleprojectcanbedownloadedasexplainedlater.Rightnow,weareinterestedinthetreesandnottheforest.

Alongwiththeexamplespresented,wewillbeidentifyingreusablecommonpatternsthatwillhelpyouinthecreationoftestsforyourownprojects.

Page 95: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThedemonstrationapplicationAverysimpleapplicationhasbeencreatedtodemonstratetheuseofsomeofthetestsinthischapter.ThesourcefortheapplicationcanbedownloadedfromXXXXXXXXXXXXX.

Thefollowingscreenshotshowsthisapplicationrunning:

Whenreadingtheexplanationofthetestsinthischapter,atanypoint,youcanrefertothedemoapplicationthatisprovidedinordertoseethetestinaction.Theprevioussimpleapplicationhasaclickablelink,textinput,clickonabuttonandadefinedlayoutUI,wecantesttheseonebyone.

Page 96: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 97: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AssertionsindepthAssertionsaremethodsthatcheckforaconditionthatcanbeevaluated.Iftheconditionisnotmet,theassertionmethodwillthrowanexception,therebyabortingtheexecutionofthetest.

TheJUnitAPIincludestheclassAssert.ThisisthebaseclassofalltheTestCaseclassesthatholdseveralassertionmethodsusefulforwritingtests.Theseinheritedmethodstestforavarietyofconditionsandareoverloadedtosupportdifferentparametertypes.Theycanbegroupedtogetherinthefollowingdifferentsets,dependingontheconditionchecked,forexample:

assertEqualsassertTrueassertFalseassertNullassertNotNullassertSameassertNotSamefail

Theconditiontestedisprettyobviousandiseasilyidentifiablebythemethodname.PerhapstheonesthatdeservesomeattentionareassertEquals()andassertSame().Theformer,whenusedonobjects,assertsthatbothobjectspassedasparametersareequallycallingtheobjects’equals()method.Thelatterassertsthatbothobjectsrefertothesameobject.If,insomecase,equals()isnotimplementedbytheclass,thenassertEquals()andassertSame()willdothesamething.

Whenoneoftheseassertionsfailsinsideatest,anAssertionFailedExceptionisthrown,andthisindicatesthatthetesthasfailed.

Occasionally,duringthedevelopmentprocess,youmightneedtocreateatestthatyouarenotimplementingatthatprecisetime.However,youwanttoflagthatthecreationofthetestwaspostponed(wedidthisinChapter1,GettingStartedwithTesting,whenweaddedjustthetestmethodstubs).Insuchcases,youcanusethefail()method,whichalwaysfailsandusesacustommessagethatindicatesthecondition:

publicvoidtestNotImplementedYet(){

fail("Notimplementedyet");

}

Still,thereisanothercommonuseforfail()thatisworthmentioning.Ifweneedtotestwhetheramethodthrowsanexception,wecansurroundthecodewithatry-catchblockandforceafailiftheexceptionwasnotthrown.Forexample:

publicvoidtestShouldThrowException(){

try{

MyFirstProjectActivity.methodThatShouldThrowException();

fail("Exceptionwasnotthrown");

}catch(Exceptionex){

Page 98: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

//donothing

}

}

NoteJUnit4hastheannotation@Test(expected=Exception.class),andthissupersedestheneedforusingfail()whentestingexceptions.Withthisannotation,thetestwillonlypassiftheexpectedexceptionisthrown.

Page 99: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CustommessagesItisworthknowingthatallassertmethodsprovideanoverloadedversionincludingacustomStringmessage.Shouldtheassertionfail,thiscustommessagewillbeprintedbythetestrunner,insteadofadefaultmessage.

Thepremisebehindthisisthat,sometimes,thegenericerrormessagedoesnotrevealenoughdetails,anditisnotobvioushowthetestfailed.Thiscustommessagecanbeextremelyusefultoeasilyidentifythefailureonceyouarelookingatthetestreport,soit’shighlyrecommendedasabestpracticetousethisversion.

Thefollowingisanexampleofasimpletestthatusesthisrecommendation:

publicvoidtestMax(){

inta=10;

intb=20;

intactual=Math.max(a,b);

StringfailMsg="Expected:"+b+"butwas:"+actual;

assertEquals(failMsg,b,actual);

}

Intheprecedingexample,wecanseeanotherpracticethatwouldhelpyouorganizeandunderstandyourtestseasily.Thisistheuseofexplicitnamesforvariablesthatholdtheactualvalues.

NoteThereareotherlibrariesavailablethathavebetterdefaulterrormessagesandalsoamorefluidinterfacefortesting.OneofthesethatisworthlookingatisFest(https://code.google.com/p/fest/).

Page 100: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

StaticimportsThoughbasicassertionmethodsareinheritedfromtheAssertbaseclass,someotherassertionsneedspecificimports.Toimprovethereadabilityofyourtests,thereisapatterntostaticallyimporttheassertmethodsfromthecorrespondingclasses.Usingthispatterninsteadofhaving:

publicvoidtestAlignment(){

intmargin=0;

...

android.test.ViewAsserts.assertRightAligned(errorMsg,editText,margin);

}

Wecansimplifyitbyaddingthestaticimport:

importstaticandroid.test.ViewAsserts.assertRightAligned;

publicvoidtestAlignment(){

intmargin=0;

assertRightAligned(errorMsg,editText,margin);

}

Page 101: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 102: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ViewassertionsTheassertionsintroducedearlierhandleavarietyoftypesasparameters,buttheyareonlyintendedtotestsimpleconditionsorsimpleobjects.

Forexample,wehaveasertEquals(shortexpected,shortactual)totestshortvalues,assertEquals(intexpected,intactual)totestintegervalues,assertEquals(Objectexpected,Objectexpected)totestanyObjectinstance,andsoon.

Usually,whiletestinguserinterfacesinAndroid,youwillfacetheproblemofmoresophisticatedmethods,whicharemainlyrelatedwithViews.Inthisrespect,Androidprovidesaclasswithplentyofassertionsinandroid.test.ViewAsserts(seehttp://developer.android.com/reference/android/test/ViewAsserts.htmlformoredetails),whichtestrelationshipsbetweenViewsandtheirabsoluteandrelativepositionsonthescreen.

Thesemethodsarealsooverloadedtoprovidedifferentconditions.Amongtheassertions,wecanfindthefollowing:

assertBaselineAligned:ThisassertsthattwoViewsarealignedontheirbaseline;thatis,theirbaselinesareonthesameylocation.assertBottomAligned:Thisassertsthattwoviewsarebottomaligned;thatis,theirbottomedgesareonthesameylocation.assertGroupContains:Thisassertsthatthespecifiedgroupcontainsaspecificchildonceandonlyonce.assertGroupIntegrity:Thisassertsthespecifiedgroup’sintegrity.Thechildcountshouldbe>=0andeachchildshouldbenon-null.assertGroupNotContains:Thisassertsthatthespecifiedgroupdoesnotcontainaspecificchild.assertHasScreenCoordinates:ThisassertsthataViewhasaparticularxandypositiononthevisiblescreen.assertHorizontalCenterAligned:ThisassertsthatthetestViewishorizontallycenteralignedwithrespecttothereferenceview.assertLeftAligned:ThisassertsthattwoViewsareleftaligned;thatis,theirleftedgesareonthesamexlocation.Anoptionalmargincanalsobeprovided.assertOffScreenAbove:Thisassertsthatthespecifiedviewisabovethevisiblescreen.assertOffScreenBelow:Thisassertsthatthespecifiedviewisbelowthevisiblescreen.assertOnScreen:ThisassertsthataViewisonthescreen.assertRightAligned:ThisassertsthattwoViewsareright-aligned;thatis,theirrightedgesareonthesamexlocation.Anoptionalmargincanalsobespecified.assertTopAligned:ThisassertsthattwoViewsaretopaligned;thatis,theirtopedgesareonthesameylocation.Anoptionalmargincanalsobespecified.assertVerticalCenterAligned:ThisassertsthatthetestViewisverticallycenter-

Page 103: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

alignedwithrespecttothereferenceView.

ThefollowingexampleshowshowyoucanuseViewAssertionstotesttheuserinterfacelayout:

publicvoidtestUserInterfaceLayout(){

intmargin=0;

Vieworigin=mActivity.getWindow().getDecorView();

assertOnScreen(origin,editText);

assertOnScreen(origin,button);

assertRightAligned(editText,button,margin);

}

TheassertOnScreenmethodusesanorigintostartlookingfortherequestedViews.Inthiscase,weareusingthetop-levelwindowdecorView.If,forsomereason,youdon’tneedtogothathighinthehierarchy,orifthisapproachisnotsuitableforyourtest,youmayuseanotherrootViewinthehierarchy,forexampleView.getRootView(),which,inourconcreteexample,wouldbeeditText.getRootView().

Page 104: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 105: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

EvenmoreassertionsIftheassertionsthatarereviewedpreviouslydonotseemtobeenoughforyourtests’needs,thereisstillanotherclassincludedintheAndroidframeworkthatcoversothercases.ThisclassisMoreAsserts(http://developer.android.com/reference/android/test/MoreAsserts.html).

Thesemethodsarealsooverloadedtosupportdifferentparametertypes.Amongtheassertions,wecanfindthefollowing:

assertAssignableFrom:Thisassertsthatanobjectisassignabletoaclass.assertContainsRegex:ThisassertsthatanexpectedRegexmatchesanysubstringofthespecifiedString.Itfailswiththespecifiedmessageifitdoesnot.assertContainsInAnyOrder:ThisassertsthatthespecifiedIterablecontainspreciselytheelementsexpected,butinanyorder.assertContainsInOrder:ThisassertsthatthespecifiedIterablecontainspreciselytheelementsexpected,butinthesameorder.assertEmpty:ThisassertsthatanIterableisempty.assertEquals:ThisisforsomeCollectionsnotcoveredinJUnitasserts.assertMatchesRegex:ThisassertsthatthespecifiedRegexexactlymatchestheStringandfailswiththeprovidedmessageifitdoesnot.assertNotContainsRegex:ThisassertsthatthespecifiedRegexdoesnotmatchanysubstringofthespecifiedString,andfailswiththeprovidedmessageifitdoes.assertNotEmpty:ThisassertsthatsomeCollectionsnotcoveredinJUnitassertsarenotempty.assertNotMatchesRegex:ThisassertsthatthespecifiedRegexdoesnotexactlymatchthespecifiedString,andfailswiththeprovidedmessageifitdoes.checkEqualsAndHashCodeMethods:Thisisautilityusedtotesttheequals()andhashCode()resultsatonce.Thistestswhetherequals()thatisappliedtobothobjectsmatchesthespecifiedresult.

ThefollowingtestchecksforanerrorduringtheinvocationofthecapitalizationmethodcalledviaaclickontheUIbutton:

@UiThreadTest

publicvoidtestNoErrorInCapitalization(){

Stringmsg="capitalizethistext";

editText.setText(msg);

button.performClick();

Stringactual=editText.getText().toString();

StringnotExpectedRegexp="(?i:ERROR)";

StringerrorMsg="Capitalizationerrorfor"+actual;

assertNotContainsRegex(errorMsg,notExpectedRegexp,actual);

}

Ifyouarenotfamiliarwithregularexpressions,investsometimeandvisithttp://developer.android.com/reference/java/util/regex/package-summary.htmlbecauseit

Page 106: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

willbeworthit!

Inthisparticularcase,wearelookingforthewordERRORcontainedintheresultwithacase-insensitivematch(settingtheflagiforthispurpose).Thatis,ifforsomereason,capitalizationdoesn’tworkinourapplication,anditcontainsanerrormessage,wecandetectthisconditionwiththeassertion.

NoteNotethatbecausethisisatestthatmodifiestheuserinterface,wemustannotateitwith@UiThreadTest;otherwise,itwon’tbeabletoaltertheUIfromadifferentthread,andwewillreceivethefollowingexception:

INFO/TestRunner(610):-----beginexception-----

INFO/TestRunner(610):android.view.ViewRoot$CalledFromWrongThreadException:

Onlytheoriginalthreadthatcreatedaviewhierarchycantouchitsviews.

INFO/TestRunner(610):at

android.view.ViewRoot.checkThread(ViewRoot.java:2932)

[...]

INFO/TestRunner(610):at

android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:

1447)

INFO/TestRunner(610):-----endexception-----

Page 107: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 108: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheTouchUtilsclassSometimes,whentestingUIs,itishelpfultosimulatedifferentkindsoftouchevents.Thesetoucheventscanbegeneratedinmanydifferentways,butprobablyandroid.test.TouchUtilsisthesimplesttouse.ThisclassprovidesreusablemethodstogeneratetoucheventsintestcasesthatarederivedfromInstrumentationTestCase.

ThefeaturedmethodsallowasimulatedinteractionwiththeUIundertest.TheTouchUtilsclassprovidestheinfrastructuretoinjecttheeventsusingthecorrectUIormainthread,sonospecialhandlingisneeded,andyoudon’tneedtoannotatethetestusing@UIThreadTest.

TouchUtilssupportsthefollowing:

ClickingonaViewandreleasingitTappingonaView(touchingitandquicklyreleasing)Long-clickingonaViewDraggingthescreenDraggingViews

ThefollowingtestrepresentsatypicalusageofTouchUtils:

publicvoidtestListScrolling(){

listView.scrollTo(0,0);

TouchUtils.dragQuarterScreenUp(this,activity);

intactualItemPosition=listView.getFirstVisiblePosition();

assertTrue("Wrongposition",actualItemPosition>0);

}

Thistestdoesthefollowing:

RepositionsthelistatthebeginningtostartfromaknownconditionScrollsthelistChecksforthefirstvisiblepositiontoseethatitwascorrectlyscrolled

EventhemostcomplexUIscanbetestedinthatway,anditwouldhelpyoudetectavarietyofconditionsthatcouldpotentiallyaffecttheuserexperience.

Page 109: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 110: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MockobjectsWehaveseenthemockobjectsprovidedbytheAndroidtestingframeworkinChapter1,GettingStartedwithTesting,andevaluatedtheconcernsaboutnotusingrealobjectstoisolateourtestsfromthesurroundingenvironment.

ThenextchapterdealswithTest-drivenDevelopment,andifwewereTest-drivenDevelopmentpurists,wecanargueabouttheuseofmockobjectsandbemoreinclinedtouserealones.MartinFowlercallsthesetwostylestheclassicalandmockistTest-drivenDevelopmentdichotomyinhisgreatarticleMocksaren’tstubs,whichcanbereadonlineathttp://www.martinfowler.com/articles/mocksArentStubs.html.

Independentofthisdiscussion,weareintroducingmockobjectsasoneoftheavailablebuildingblocksbecause,sometimes,usingmockobjectsinourtestsisrecommended,desirable,useful,orevenunavoidable.

TheAndroidSDKprovidesthefollowingclassesinthesubpackageandroid.test.mocktohelpus:

MockApplication:ThisisamockimplementationoftheApplicationclass.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockContentProvider:ThisisamockimplementationofContentProvider.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockContentResolver:ThisisamockimplementationoftheContentResolverclassthatisolatesthetestcodefromtherealcontentsystem.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockContext:Thisisamockcontextclass,andthiscanbeusedtoinjectotherdependencies.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockCursor:ThisisamockCursorclassthatisolatesthetestcodefromrealCursorimplementation.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockDialogInterface:ThisisamockimplementationoftheDialogInterfaceclass.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockPackageManager:ThisisamockimplementationofthePackageManagerclass.Allmethodsarenon-functionalandthrowUnsupportedOperationException.MockResources:ThisisamockResourcesclass.

Alloftheseclasseshavenon-functionalmethodsthatthrowUnsupportedOperationExceptionwhenused.Ifyouneedtousesomeofthesemethods,orifyoudetectthatyourtestisfailingwiththisException,youshouldextendoneofthesebaseclassesandprovidetherequiredfunctionality.

Page 111: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AnoverviewofMockContextThismockcanbeusedtoinjectotherdependencies,mocks,ormonitorsintotheclassesundertest.Extendthisclasstoprovideyourdesiredbehavior,overridingthecorrespondentmethods.TheAndroidSDKprovidessomeprebuiltmockContextobjects,eachofwhichhasaseparateusecase.

Page 112: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheIsolatedContextclassInyourtests,youmightfindtheneedtoisolatetheActivityundertestfromotherAndroidcomponentstopreventunwantedinteractions.Thiscanbeacompleteisolation,butsometimes,thisisolationavoidsinteractingwithothercomponents,andforyourActivitytostillruncorrectly,someconnectionwiththesystemisrequired.

Forthosecases,theAndroidSDKprovidesandroid.test.IsolatedContext,amockContextthatnotonlypreventsinteractionwithmostoftheunderlyingsystembutalsosatisfiestheneedsofinteractingwithotherpackagesorcomponentssuchasServicesorContentProviders.

Page 113: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AlternateroutetofileanddatabaseoperationsInsomecases,allweneedistobeabletoprovideanalternateroutetothefileanddatabaseoperations.Forexample,ifwearetestingtheapplicationonarealdevice,weperhapsdon’twanttoaffecttheexistingdatabasebutuseourowntestingdata.

Suchcasescantakeadvantageofanotherclassthatisnotpartoftheandroid.test.mocksubpackagebutispartofandroid.testinstead,thatis,RenamingDelegatingContext.

Thisclassletsusalteroperationsonfilesanddatabasesbyhavingaprefixthatisspecifiedintheconstructor.AllotheroperationsaredelegatedtothedelegatingContextthatyoumustspecifyintheconstructortoo.

SupposeourActivityundertestusesadatabasewewanttocontrol,probablyintroducingspecializedcontentorfixturedatatodriveourtests,andwedon’twanttousetherealfiles.Inthiscase,wecreateaRenamingDelegatingContextclassthatspecifiesaprefix,andourunchangedActivitywillusethisprefixtocreateanyfiles.

Forexample,ifourActivitytriestoaccessafilenamedbirthdays.txt,andweprovideaRenamingDelegatingContextclassthatspecifiestheprefixtest,thenthissameActivitywillaccessthefiletestbirthdays.txtinsteadwhenitisbeingtested.

Page 114: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheMockContentResolverclassTheMockContentResolverclassimplementsallmethodsinanon-functionalwayandthrowstheexceptionUnsupportedOperationExceptionifyouattempttousethem.Thereasonforthisclassistoisolatetestsfromtherealcontent.

Let’ssayyourapplicationusesaContentProviderclasstofeedyourActivityinformation.YoucancreateunittestsforthisContentProviderusingProviderTestCase2,whichwewillbeanalyzingshortly,butwhenwetrytoproducefunctionalorintegrationtestsfortheActivityagainstContentProvider,it’snotsoevidentastowhattestcasetouse.ThemostobviouschoiceisActivityInstrumentationTestCase2,mainlyifyourfunctionaltestssimulateuserexperiencebecauseyoumightneedthesendKeys()methodorsimilarmethods,whicharereadilyavailableonthesetests.

Thefirstproblemyoumightencounterthenisthatit’sunclearastowheretoinjectaMockContentResolverinyourtesttobeabletousetestdatawithyourContentProvider.There’snowaytoinjectaMockContexteither.

ThisproblemwillbesolvedinChapter3,BakingwithTestingRecipeswherefurtherdetailsareprovided.

Page 115: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 116: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheTestCasebaseclassThisisthebaseclassofallothertestcasesintheJUnitframework.Itimplementsthebasicmethodsthatwewereanalyzinginthepreviousexamples(setUp()).TheTestCaseclassalsoimplementsthejunit.framework.Testinterface,meaningitcanberunasaJUnittest.

YourAndroidtestcasesshouldalwaysextendTestCaseoroneofitsdescendants.

Page 117: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThedefaultconstructorAlltestcasesrequireadefaultconstructorbecause,sometimes,dependingonthetestrunnerused,thisistheonlyconstructorthatisinvoked,andisalsousedforserialization.

Accordingtothedocumentation,thismethodisnotintendedtobeusedby“meremortals”withoutcallingsetName(Stringname).

Therefore,toappeasetheGods,acommonpatternistouseadefaulttestcasenameinthisconstructorandinvokethegivennameconstructorafterwards:

publicclassMyTestCaseextendsTestCase{

publicMyTestCase(){

this("MyTestCaseDefaultName");

}

publicMyTestCase(Stringname){

super(name);

}

}

TipDownloadingtheexamplecode

Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Page 118: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThegivennameconstructorThisconstructortakesanameasanargumenttolabelthetestcase.Itwillappearintestreportsandwouldbeofmuchhelpwhenyoutrytoidentifywherefailedtestshavecomefrom.

Page 119: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThesetName()methodTherearesomeclassesthatextendTestCasethatdon’tprovideagivennameconstructor.Insuchcases,theonlyalternativeistocallsetName(Stringname).

Page 120: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 121: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheAndroidTestCasebaseclassThisclasscanbeusedasabaseclassforgeneral-purposeAndroidtestcases.

UseitwhenyouneedaccesstoAndroidresources,databases,orfilesinthefilesystem.Contextisstoredasafieldinthisclass,whichisconvenientlynamedmContextandcanbeusedinsidethetestsifneeded,orthegetContext()methodcanbeusedtoo.

TestsbasedonthisclasscanstartmorethanoneActivityusingContext.startActivity().

TherearevarioustestcasesinAndroidSDKthatextendthisbaseclass:

ApplicationTestCase<TextendsApplication>

ProviderTestCase2<TextendsContentProvider>

ServiceTestCase<TextendsService>

WhenusingtheAndroidTestCaseJavaclass,youinheritsomebaseassertionmethodsthatcanbeused;let’slookattheseinmoredetail.

Page 122: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheassertActivityRequiresPermission()methodThesignatureforthismethodisasfollows:

publicvoidassertActivityRequiresPermission(StringpackageName,String

className,Stringpermission)

DescriptionThisassertionmethodcheckswhetherthelaunchingofaparticularActivityisprotectedbyaspecificpermission.Ittakesthefollowingthreeparameters:

packageName:ThisisastringthatindicatesthepackagenameoftheactivitytolaunchclassName:Thisisastringthatindicatestheclassoftheactivitytolaunchpermission:Thisisastringwiththepermissiontocheck

TheActivityislaunchedandthenSecurityExceptionisexpected,whichmentionsthattherequiredpermissionismissingintheerrormessage.Theactualinstantiationofanactivityisnothandledbythisassertion,andthus,anInstrumentationisnotneeded.

ExampleThistestcheckstherequirementoftheandroid.Manifest.permission.WRITE_EXTERNAL_STORAGEpermission,whichisneededtowritetoexternalstorage,intheMyContactsActivityActivity:

publicvoidtestActivityPermission(){

Stringpkg="com.blundell.tut";

Stringactivity=PKG+".MyContactsActivity";

Stringpermission=android.Manifest.permission.CALL_PHONE;

assertActivityRequiresPermission(pkg,activity,permission);

}

TipAlwaysusetheconstantsthatdescribethepermissionsfromandroid.Manifest.permission,notthestrings,soiftheimplementationchanges,yourcodewillstillbevalid.

Page 123: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheassertReadingContentUriRequiresPermissionmethodThesignatureforthismethodisasfollows:

publicvoidassertReadingContentUriRequiresPermission(Uriuri,String

permission)

DescriptionThisassertionmethodcheckswhetherreadingfromaspecificURIrequiresthepermissionprovidedasaparameter.

Ittakesthefollowingtwoparameters:

uri:ThisistheUrithatrequiresapermissiontoquerypermission:Thisisastringthatcontainsthepermissiontoquery

IfaSecurityExceptionclassisgenerated,whichcontainsthespecifiedpermission,thisassertionisvalidated.

ExampleThistesttriestoreadcontactsandverifiesthatthecorrectSecurityExceptionisgenerated:

publicvoidtestReadingContacts(){

UriURI=ContactsContract.AUTHORITY_URI;

StringPERMISSION=android.Manifest.permission.READ_CONTACTS;

assertReadingContentUriRequiresPermission(URI,PERMISSION);

}

Page 124: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheassertWritingContentUriRequiresPermission()methodThesignatureforthismethodisasfollows:

publicvoidassertWritingContentUriRequiresPermission(Uriuri,String

permission)

DescriptionThisassertionmethodcheckswhetherinsertingintoaspecificUrirequiresthepermissionprovidedasaparameter.

Ittakesthefollowingtwoparameters:

uri:ThisistheUrithatrequiresapermissiontoquerypermission:Thisisastringthatcontainsthepermissiontoquery

IfaSecurityExceptionclassisgenerated,whichcontainsthespecifiedpermission,thisassertionisvalidated.

ExampleThistesttriestowritetoContactsandverifiesthatthecorrectSecurityExceptionisgenerated:

publicvoidtestWritingContacts(){

Uriuri=ContactsContract.AUTHORITY_URI;

Stringpermission=android.Manifest.permission.WRITE_CONTACTS;

assertWritingContentUriRequiresPermission(uri,permission);

}

Page 125: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 126: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

InstrumentationInstrumentationisinstantiatedbythesystembeforeanyoftheapplicationcodeisrun,therebyallowingmonitoringofalltheinteractionsbetweenthesystemandtheapplication.

AswithmanyotherAndroidapplicationcomponents,instrumentationimplementationsaredescribedintheAndroidManifest.xmlunderthetag<instrumentation>.However,withtheadventofGradle,thishasnowbeenautomatedforus,andwecanchangethepropertiesoftheinstrumentationintheapp’sbuild.gradlefile.TheAndroidManifestfileforyourtestswillbeautomaticallygenerated:

defaultConfig{

testApplicationId'com.blundell.tut.tests'

testInstrumentationRunner"android.test.InstrumentationTestRunner"

}

Thevaluesmentionedintheprecedingcodearealsothedefaultsifyoudonotdeclarethem,meaningthatyoudon’thavetohaveanyoftheseparameterstostartwritingtests.

ThetestApplicationIdattributedefinesthenameofthepackageforyourtests.Asadefault,itisyourapplicationunderthetestpackagename+tests.YoucandeclareacustomtestrunnerusingtestInstrumentationRunner.Thisishandyifyouwanttohavetestsruninacustomway,forexample,paralleltestexecution.

Therearealsomanyotherparametersindevelopment,andIwouldadviseyoutokeepyoureyesupontheGoogleGradlepluginwebsite(http://tools.android.com/tech-docs/new-build-system/user-guide).

Page 127: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheActivityMonitorinnerclassAsmentionedearlier,theInstrumentationclassisusedtomonitortheinteractionbetweenthesystemandtheapplicationortheActivitiesundertest.TheinnerclassInstrumentationActivityMonitorallowsthemonitoringofasingleActivitywithinanapplication.

ExampleLet’spretendthatwehaveaTextViewinourActivitythatholdsaURLandhasitsautolinkpropertyset:

<TextView

android:id="@+id/link

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="@string/home"

android:autoLink="web""/>

Ifwewanttoverifythat,whenclicked,thehyperlinkiscorrectlyfollowedandsomebrowserisinvoked,wecancreateatestlikethis:

publicvoidtestFollowLink(){

IntentFilterintentFilter=newIntentFilter(Intent.ACTION_VIEW);

intentFilter.addDataScheme("http");

intentFilter.addCategory(Intent.CATEGORY_BROWSABLE);

Instrumentationinst=getInstrumentation();

ActivityMonitormonitor=inst.addMonitor(intentFilter,null,

false);

TouchUtils.clickView(this,linkTextView);

monitor.waitForActivityWithTimeout(3000);

intmonitorHits=monitor.getHits();

inst.removeMonitor(monitor);

assertEquals(1,monitorHits);

}

Here,wewilldothefollowing:

1. CreateanIntentFilterforintentsthatwouldopenabrowser.2. AddamonitortoourInstrumentationbasedontheIntentFilterclass.3. Clickonthehyperlink.4. Waitfortheactivity(hopefullythebrowser).5. Verifythatthemonitorhitswereincremented.6. Removethemonitor.

Usingmonitors,wecantesteventhemostcomplexinteractionswiththesystemandotherActivities.Thisisaverypowerfultooltocreateintegrationtests.

Page 128: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 129: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheInstrumentationTestCaseclassTheInstrumentationTestCaseclassisthedirectorindirectbaseclassforvarioustestcasesthathaveaccesstoInstrumentation.Thisisthelistofthemostimportantdirectandindirectsubclasses:

ActivityTestCase

ProviderTestCase2<TextendsContentProvider>

SingleLaunchActivityTestCase<TextendsActivity>

SyncBaseInstrumentation

ActivityInstrumentationTestCase2<TextendsActivity>

ActivityUnitTestCase<TextendsActivity>

TheInstrumentationTestCaseclassisintheandroid.testpackage,andextendsjunit.framework.TestCase,whichextendsjunit.framework.Assert.

Page 130: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThelaunchActivityandlaunchActivityWithIntentmethodsTheseutilitymethodsareusedtolaunchActivitiesfromatest.IftheIntentisnotspecifiedusingthesecondoption,adefaultIntentisused:

publicfinalTlaunchActivity(Stringpkg,Class<T>activityCls,Bundle

extras)

NoteThetemplateclassparameterTisusedinactivityClsandasthereturntype,limitingitsusetoActivitiesofthattype.

IfyouneedtospecifyacustomIntent,youcanusethefollowingcodethatalsoaddstheintentparameter:

publicfinalTlaunchActivityWithIntent(Stringpkg,Class<T>activityCls,

Intentintent)

Page 131: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThesendKeysandsendRepeatedKeysmethodsWhiletestingActivities’UI,youwillfacetheneedtosimulateinteractionwithqwerty-basedkeyboardsorDPADbuttonstosendkeystocompletefields,selectshortcuts,ornavigatethroughoutthedifferentcomponents.

ThisiswhatthedifferentsendKeysandsendRepeatedKeysareusedfor.

ThereisoneversionofsendKeysthatacceptsintegerkeysvalues.TheycanbeobtainedfromconstantsdefinedintheKeyEventclass.

Forexample,wecanusethesendKeysmethodinthisway:

publicvoidtestSendKeyInts(){

requestMessageInputFocus();

sendKeys(

KeyEvent.KEYCODE_H,

KeyEvent.KEYCODE_E,

KeyEvent.KEYCODE_E,

KeyEvent.KEYCODE_E,

KeyEvent.KEYCODE_Y,

KeyEvent.KEYCODE_DPAD_DOWN,

KeyEvent.KEYCODE_ENTER);

Stringactual=messageInput.getText().toString();

assertEquals("HEEEY",actual);

}

Here,wearesendingH,E,andYletterkeysandthentheENTERkeyusingtheirintegerrepresentationstotheActivityundertest.

Alternatively,wecancreateastringbyconcatenatingthekeyswedesiretosend,discardingtheKEYCODEprefix,andseparatingthemwithspacesthatareultimatelyignored:

publicvoidtestSendKeyString(){

requestMessageInputFocus();

sendKeys("H3*EYDPAD_DOWNENTER");

Stringactual=messageInput.getText().toString();

assertEquals("HEEEY",actual);

}

Here,wedidexactlythesameasintheprevioustestbutweusedaString"H3*EYDPAD_DOWNENTER".NotethateverykeyintheStringcanbeprefixedbyarepeatingfactorfollowedby*andthekeytoberepeated.Weused3*Einourpreviousexample,whichisthesameasEEE,thatis,threetimestheletterE.

Ifsendingrepeatedkeysiswhatweneedinourtests,thereisalsoanotheralternativethatispreciselyintendedforthesecases:

publicvoidtestSendRepeatedKeys(){

requestMessageInputFocus();

Page 132: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

sendRepeatedKeys(

1,KeyEvent.KEYCODE_H,

3,KeyEvent.KEYCODE_E,

1,KeyEvent.KEYCODE_Y,

1,KeyEvent.KEYCODE_DPAD_DOWN,

1,KeyEvent.KEYCODE_ENTER);

Stringactual=messageInput.getText().toString();

assertEquals("HEEEY",actual);

}

Thisisthesametestimplementedinadifferentmanner.Therepetitionnumberprecedeseachkey.

Page 133: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TherunTestOnUiThreadhelpermethodTherunTestOnUiThreadmethodisahelpermethodusedtorunportionsofatestontheUIthread.WeusedthisinsidethemethodrequestMessageInputFocus();sothatwecansetthefocusonourEditTextbeforewaitingfortheapplicationtobeidle,usingInstrumentation.waitForIdleSync().Also,therunTestOnUiThreadmethodthrowsanexception,sowehavetodealwiththiscase:

privatevoidrequestMessageInputFocus(){

try{

runTestOnUiThread(newRunnable(){

@Override

publicvoidrun(){

messageInput.requestFocus();

}

});

}catch(Throwablethrowable){

fail("Couldnotrequestfocus.");

}

instrumentation.waitForIdleSync();

}

Alternatively,aswehavediscussedbefore,torunatestontheUIthread,[email protected],sometimes,weneedtorunonlypartsofthetestontheUIthreadbecauseotherpartsofitarenotsuitabletorunonthatthread,forexample,databasecalls,orweareusingotherhelpermethodsthatprovidetheinfrastructurethemselvestousetheUIthread,forexampletheTouchUtilsmethods.

Page 134: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 135: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheActivityTestCaseclassThisismainlyaclassthatholdscommoncodeforothertestcasesthataccessInstrumentation.

Youcanusethisclassifyouareimplementingaspecificbehaviorfortestcasesandtheexistingalternativesdon’tfityourrequirements.Thismeansyouareunlikelytousethisclassunlessyouwanttoimplementanewbaseclassforotherteststouse.Forexample,considerascenariowhereGooglebringsoutanewcomponentandyouwanttowritetestsaroundit(likeSuperNewContentProvider).

Ifthisisnotthecase,youmightfindthefollowingoptionsmoresuitableforyourrequirements:

ActivityInstrumentationTestCase2<TextendsActivity>

ActivityUnitTestCase<TextendsActivity>

Theabstractclassandroid.test.ActivityTestCaseextendsandroid.test.InstrumentationTestCaseandservesasabaseclassforotherdifferenttestcases,suchasandroid.test.ActivityInstrumentationTestCase,android.test.ActivityInstrumentationTestCase2,andandroid.test.ActivityUnitTestCase.

NoteTheandroid.test.ActivityInstrumentationTestCasetestcaseisadeprecatedclasssinceAndroidAPILevel3(Android1.5)andshouldnotbeusedinnewerprojects.Eventhoughitwasdeprecatedlongago,ithasagreatnameforautoimport,sobecareful!

Page 136: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThescrubClassmethodThescrubClassmethodisoneoftheprotectedmethodsintheclass:

protectedvoidscrubClass(Class<?>testCaseClass)

ItisinvokedfromthetearDown()methodinseveralofthediscussedtestcaseimplementationsinordertocleanupclassvariablesthatmayhavebeeninstantiatedasnon-staticinnerclassessoastoavoidholdingreferencestothem.

Thisisinordertopreventmemoryleaksforlargetestsuites.

IllegalAccessExceptionisthrownifaproblemisencounteredwhileaccessingtheseclassvariables.

Page 137: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 138: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheActivityInstrumentationTestCase2classTheActivityInstrumentationTestCase2classwouldprobablybetheoneyouusethemosttowritefunctionalAndroidtestcases.ItprovidesfunctionaltestingofasingleActivity.

ThisclasshasaccesstoInstrumentationandwillcreatetheActivityundertestusingthesysteminfrastructure,bycallingInstrumentationTestCase.launchActivity().TheActivitycanthenbemanipulatedandmonitoredaftercreation.

IfyouneedtoprovideacustomIntenttostartyourActivity,beforeinvokinggetActivity(),youmayinjectanIntentwithsetActivityIntent(Intentintent).

Thistestcasewouldbeveryusefultotestinteractionsthroughtheuserinterfaceaseventscanbeinjectedtosimulateuserbehavior.

Page 139: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheconstructorThereisonlyonepublicnon-deprecatedconstructorforthisclass,whichisasfollows:

ActivityInstrumentationTestCase2(Class<T>activityClass)

ItshouldbeinvokedwithaninstanceoftheActivityclassforthesameActivityusedasaclasstemplateparameter.

Page 140: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThesetUpmethodThesetUpmethodisthepreciseplacetoinitializethetestcasefieldsandotherfixturecomponentsthatrequireinitialization.

Thisisanexamplethatshowssomeofthepatternsthatyoumightrepeatedlyfindinyourtestcases:

@Override

protectedvoidsetUp()throwsException{

super.setUp();

//thismustbecalledbeforegetActivity()

//disablingtouchmodeallowsforsendingkeyevents

setActivityInitialTouchMode(false);

activity=getActivity();

instrumentation=getInstrumentation();

linkTextView=(TextView)activity.findViewById(R.id.main_text_link);

messageInput=(EditText)

activity.findViewById(R.id.main_input_message);

capitalizeButton=(Button)

activity.findViewById(R.id.main_button_capitalize);

}

Weperformthefollowingactions:

1. Invokethesupermethod.ThisisaJUnitpatternthatshouldbefollowedheretoensurecorrectoperation.

2. Disablethetouchmode.Totakeeffect,thisshouldbedonebeforetheActivityiscreated,byinvokinggetActivity().ItsetstheinitialtouchmodeoftheActivityundertestasdisabled.ThetouchmodeisafundamentalAndroidUIconcept,andisdiscussedinhttp://developer.android.com/guide/topics/ui/ui-events.html#TouchMode.

3. StarttheActivityusinggetActivity().4. Gettheinstrumentation.Wehaveaccesstotheinstrumentationbecause

ActivityInstrumentationTestCase2extendsInstrumentationTestCase.5. FindtheViewsandsetthefields.Intheseoperations,notethattheRclassusedis

fromthetargetpackageandnotfromthetests.

Page 141: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThetearDownmethodUsually,thismethodcleansupwhatwasinitializedinsetUp.Forinstance,ifyouwerecreatinganintegrationtestthatsetsupamockwebserverbeforeyourtests,youwouldwanttotearitbackdownafterwardstofreeupresources.

Inthisexample,weensurethattheobjectweusedisdisposedof:

@Override

protectedvoidtearDown()throwsException{

super.tearDown();

myObject.dispose();

}

Page 142: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 143: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheProviderTestCase2<T>classThisisatestcasedesignedtotesttheContentProviderclasses.

TheProviderTestCase2classalsoextendsAndroidTestCase.TheclasstemplateparameterTrepresentsContentProviderundertest.ImplementationofthistestusesIsolatedContextandMockContentResolver,whicharemockobjectsthatwedescribedbeforeinthischapter.

Page 144: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheconstructorThereisonlyonepublicnon-deprecatedconstructorforthisclass.Thisisasfollows:

ProviderTestCase2(Class<T>providerClass,StringproviderAuthority)

ThisshouldbeinvokedwithaninstanceoftheContentProviderclassforthesameContentProviderclassusedasaclasstemplateparameter.

Thesecondparameteristheauthorityfortheprovider,whichisusuallydefinedastheAUTHORITYconstantintheContentProviderclass.

Page 145: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AnexampleThisisatypicalexampleofaContentProvidertest:

publicvoidtestQuery(){

Stringsegment="dummySegment";

Uriuri=Uri.withAppendedPath(MyProvider.CONTENT_URI,segment);

Cursorc=provider.query(uri,null,null,null,null);

try{

intactual=c.getCount();

assertEquals(2,actual);

}finally{

c.close();

}

}

Inthistest,weareexpectingthequerytoreturnaCursorthatcontainstworows(thisisjustanexamplethatusesthenumberofrowsthatappliesforyourparticularcase)andassertsthiscondition.

Usually,inthesetUpmethod,weobtainareferencetothemProviderproviderinthisexample,usinggetProvider().

WhatisinterestingtonoteisthatbecausethesetestsareusingMockContentResolverandIsolatedContext,thecontentoftherealdatabaseisnotaffected,andwecanalsorundestructivetestslikethisone:

publicvoidtestDeleteByIdDeletesCorrectNumberOfRows(){

Stringsegment="dummySegment";

Uriuri=Uri.withAppendedPath(MyProvider.CONTENT_URI,segment);

intactual=provider.delete(uri,"_id=?",newString[]{"1"});

assertEquals(1,actual);

}

Thistestdeletessomecontentfromthedatabase,butthedatabaseisrestoredtoitsinitialcontentafterwardsnottoaffectothertests.

Page 146: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 147: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheServiceTestCase<T>Thisisatestcasespeciallycreatedtotestservices.Themethodstoexercisetheservicelifecycle,suchassetupService,startService,bindService,andshutDownService,arealsoincludedinthisclass.

Page 148: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheconstructorThereisonlyonepublicnon-deprecatedconstructorforthisclass.Thisisasfollows:

ServiceTestCase(Class<T>serviceClass)

ItshouldbeinvokedwithaninstanceoftheServiceclassforthesameServiceusedasaclasstemplateparameter.

Page 149: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 150: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheTestSuiteBuilder.FailedToCreateTestsclassTheTestSuiteBuilder.FailedToCreateTestsclassisaspecialTestCaseclassusedtoindicateafailureduringthebuild()step.Thatis,duringthetestsuitecreation,ifanerrorisdetected,youwillreceiveanexceptionlikethisone,whichindicatesthefailuretoconstructthetestsuite:

INFO/TestRunner(1):java.lang.RuntimeException:Exceptionduringsuite

construction

INFO/TestRunner(1):at

android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests.testSuiteCon

structionFailed(TestSuiteBuilder.java:239)

INFO/TestRunner(1):atjava.lang.reflect.Method.invokeNative(Native

Method)

[...]

INFO/TestRunner(1):at

android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.ja

va:520)

INFO/TestRunner(1):at

android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:

1447)

Page 151: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 152: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

UsinglibrariesintestprojectsYourAndroidprojectmightrequireanexternalJavalibraryoranAndroidlibrary.Now,wewillexplainhowtoincorporatetheseinyourprojectthatisreadytobetested.NotethatthefollowingexplainstheusageofalocalmodulethatisanAndroidlibrary,butthesamerulescanbeappliedtoanexternalJAR(Javalibrary)fileoranexternalAAR(Androidlibrary)file.

Let’spretendthatinoneActivity,wearecreatingobjectsfromaclassthatispartofalibrary.Forthesakeofourexample,let’ssaythelibraryiscalleddummyLibrary,andthementionedclassisDummy.

SoourActivitywouldlooklikethis:

importcom.blundell.dummylibrary.Dummy;

publicclassMyFirstProjectActivityextendsActivity{

privateDummydummy;

@Override

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

finalEditTextmessageInput=(EditText)

findViewById(R.id.main_input_message);

ButtoncapitalizeButton=(Button)

findViewById(R.id.main_button_capitalize);

capitalizeButton.setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

Stringinput=messageInput.getText().toString();

messageInput.setText(input.toUpperCase());

}

});

dummy=newDummy();

}

publicDummygetDummy(){

returndummy;

}

publicstaticvoidmethodThatShouldThrowException()throwsException{

thrownewException("Thisisanexception");

}

}

ThislibraryisanAndroidAARmodule,andsoitshouldbeaddedtoyourbuild.gradledependenciesinthenormalway:

dependencies{

compileproject(':dummylibrary')

Page 153: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

}

Ifthiswasanexternallibrary,youwouldreplaceproject(':dummylibrary')with'com.external.lib:name:version'.

Now,let’screateasimpletest.Fromourpreviousexperience,weknowthatifweneedtotestanActivity,weshoulduseActivityInstrumentationTestCase2,andthisispreciselywhatwewilldo.Oursimpletestwillbeasfollows:

publicvoidtestDummy(){

assertNotNull(activity.getDummy());

}

Thetestintheprecedingcoderunsandpassesinthefirstinstance!Notethatinthenot-so-distantpast(pre-Gradle),thetestwouldnothaveevencompiled.Wewouldhavehadtojumpthroughhoops,addingthetestlibrarytoourAndroidtestsproject,ormakingtheJAR/AARfileexportablefromourmainproject.It’sanicetimetostopandreflectonthepowerofGradleandAndroidStudiothatgiveusalotofmanualsetupforfree.

Page 154: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 155: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryWeinvestigatedthemostrelevantbuildingblocksandreusablepatternstocreateourtests.Alongthisjourney,we:

UnderstoodthecommonassertionsfoundinJUnittestsExplainedthespecializedassertionsfoundintheAndroidSDKExploredAndroidmockobjectsandtheiruseinAndroidtestsExemplifiedtheuseofthedifferenttestcasesavailableintheAndroidSDK

Nowthatwehaveallthebuildingblocks,itistimetostartcreatingmoreandmoreteststoacquiretheexperienceneededtomasterthetechnique.

ThenextchapterwillprovideyouwithexamplesofwhenandwheretousedifferenttestcasesonAndroid.Thiswillgiveusagreatbreadthofexpertiseinknowingwhattestingmethodologytoapplywhenwehaveaspecificscenariototest.

Page 156: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 157: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter3.BakingwithTestingRecipesThischapterprovidespracticalexamplesofmultiplecommonsituationsthatyouwillencounter,byapplyingthedisciplinesandtechniquesdescribedinthepreviouschapters.Theexamplesarepresentedinaneasy-to-followmanner,soyoucanadaptandusethemforyourownprojects.

Thefollowingarethetopicsthatwillbecoveredinthischapter:

AndroidunittestsTestingactivitiesandapplicationsTestingdatabasesandcontentprovidersTestinglocalandremoteservicesTestinguserinterfacesTestingexceptionsTestingparsersTestingformemoryleaksTestingwithEspresso

Afterthischapter,youwillhaveareferencetoapplydifferenttestingrecipestoyourprojectsfordifferentsituations.

Page 158: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AndroidunittestsTherearesomecaseswhereyoureallyneedtotestpartsoftheapplicationinisolationwithlittleconnectiontotheunderlyingsystem.InAndroid,thesystemistheActivityframework.Insuchcases,wehavetoselectabaseclassthatishighenoughinthetesthierarchytoremovesomeofthedependenciesbutnothighenoughforustoberesponsibleforsomeofthebasicinfrastructureofinstantiatingContext,forexample.

Insuchcases,thecandidatebaseclassisAndroidTestCasebecausethisallowstheuseofContextandResourceswithoutthinkingaboutActivities:

publicclassAccessPrivateDataTestextendsAndroidTestCase{

publicvoidtestAccessAnotherAppsPrivateDataIsNotPossible(){

StringfilesDirectory=getContext().getFilesDir().getPath();

StringprivateFilePath=filesDirectory+

"/data/com.android.cts.appwithdata/private_file.txt";

try{

newFileInputStream(privateFilePath);

fail("Wasabletoaccessanotherapp'sprivatedata");

}catch(FileNotFoundExceptione){

//expected

}

}

}

TipThisexampleisbasedontheAndroidCompatibilityTestSuite(CTS)athttp://source.android.com/compatibility/cts-intro.html.TheCTSisasuiteoftestsaimedatmakingtheAndroidhardwareandsoftwareenvironmentconsistentforapplicationdevelopers,irrespectiveoftheoriginalequipmentmanufacturer.

TheAccessPrivateDataTestclassextendsAndroidTestCasebecauseit’saunittestthatdoesn’trequirethesysteminfrastructure.Inthisparticularcase,wecouldnothaveusedTestCasedirectlybecauseweareusinggetContext()lateron.

Thistestmethod,testAccessAnotherAppsPrivateDataIsNotPossible(),teststheaccesstoanotherpackage’sprivatedataandfailsifaccessispossible.Toachievethis,theexpectedexceptionsarecaught,andifthisdoesn’thappen,fail()isinvokedwithacustommessage.Thetestseemsprettystraightforward,butyoucanseehowpowerfulthisistostopinadvertentsecuritymistakesfromcreepingin.

Page 159: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 160: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingactivitiesandapplicationsHere,wecoversomecommoncasesthatyouwillfindinyourday-to-daytesting,includingdealingwithIntents,Preferences,andContext.Youcanadaptthesepatternstosuityourspecificneeds.

Page 161: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MockingapplicationsandpreferencesInAndroidparlance,anapplicationreferstoabaseclassusedwhenitisneededtomaintainaglobalapplicationstate.Thefullpackageisandroid.app.Application.Thiscanbeutilizedwhendealingwithsharedpreferences.

Weexpectthattheteststhatalterthesepreferences’valueswillnotaffectthebehavioroftherealapplication.Withoutthecorrecttestingframework,thetestscoulddeleteuseraccountinformationforanapplicationthatstoresthesevaluesassharedpreferences.Thisdoesn’tsoundlikeagoodidea.SowhatwereallyneedistheabilitytomockaContextthatalsomockstheaccesstoSharedPreferences.

OurfirstattemptcouldbetouseRenamingDelegatingContext,butunfortunately,itdoesnotmockSharedPreferences,althoughitisclosebecauseitmocksthedatabaseandfilesystemaccess.Sofirst,weneedtomockaccesstooursharedpreferences.

TipWheneveryoucomeacrossanewclass(likeRenamingDelegatingContext),it’sagoodideatoreadtherelevantJavadoctogetanoverviewofhowtheframeworkdevelopersexpectittobeused.Formoreinformation,refertohttp://developer.android.com/reference/android/test/RenamingDelegatingContext.html.

TheRenamingMockContextclassLet’screatethespecializedContext.TheRenamingDelegatingContextclassisaverygoodpointtostartfrombecauseaswementionedbefore,databaseandfilesystemaccesswillbemocked.TheproblemishowtomocktheSharedPreferencesaccess.

RememberthatRenamingDelegatingContext,asitsnamesuggests,delegateseverythingtoaContext.SotherootofourproblemliesinthisContext.WhenyouaccessSharedPreferencesfromaContext,youusegetSharedPreferences(Stringname,intmode).Tochangethewaythismethodworks,wecanoverrideitinsideRenamingMockContext.Nowthatwehavecontrol,wecanprependthenameparameterwithourtestprefix,whichmeansthatwhenourtestsrun,theywillwritetoapreferencesfilethatisdifferentthanthatofourmainapplication:

publicclassRenamingMockContextextendsRenamingDelegatingContext{

privatestaticfinalStringPREFIX="test.";

publicRenamingMockContext(Contextcontext){

super(context,PREFIX);

}

@Override

publicSharedPreferencesgetSharedPreferences(Stringname,intmode){

returnsuper.getSharedPreferences(PREFIX+name,mode);

}

}

Now,wehavefullcontroloverhowpreferences,databases,andfilesarestored.

Page 162: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MockingcontextsWehavetheRenamingMockContextclass.Now,weneedatestthatusesit.Aswewillbetestinganapplication,thebaseclassforthetestwouldbeApplicationTestCase.Thistestcaseprovidesaframeworkinwhichyoucantestapplicationclassesinacontrolledenvironment.Itprovidesbasicsupportforthelifecycleofanapplication,andhookstoinjectvariousdependenciesandcontroltheenvironmentinwhichyourapplicationistested.UsingthesetContext()method,wecaninjecttheRenamingMockContextmethodbeforetheapplicationiscreated.

We’regoingtotestanapplicationcalledTemperatureConverter.ThisisasimpleapplicationthatconvertsCelsiustoFahrenheitandviceversa.WewilldiscussmoreaboutthedevelopmentofthisappinChapter6,PracticingTest-drivenDevelopment.Fornow,thedetailsaren’tnecessaryasweareconcentratingontestingscenarios.TheTemperatureConverterapplicationwillstorethedecimalplacesofanyconversionasasharedpreference.Consequently,wewillcreateatesttosetthedecimalplacesandthenretrieveittoverifyitsvalue:

publicclassTemperatureConverterApplicationTestsextends

ApplicationTestCase<TemperatureConverterApplication>{

publicTemperatureConverterApplicationTests(){

this("TemperatureConverterApplicationTests");

}

publicTemperatureConverterApplicationTests(Stringname){

super(TemperatureConverterApplication.class);

setName(name);

}

publicvoidtestSetAndRetreiveDecimalPlaces(){

RenamingMockContextmockContext=new

RenamingMockContext(getContext());

setContext(mockContext);

createApplication();

TemperatureConverterApplicationapplication=getApplication();

application.setDecimalPlaces(3);

assertEquals(3,application.getDecimalPlaces());

}

}

WeextendApplicationTestCaseusingtheTemperatureConverterApplicationtemplateparameter.

Then,weusethegivennameconstructorpatternthatwediscussedinChapter2,UnderstandingTestingwiththeAndroidSDK.

Here,wehavenotusedasetUp()methodsincethereisonlyonetestintheclass–youain’tgonnaneeditastheysay.Oneday,ifyoucometoaddanothertesttothisclass,thisiswhenyoucanoverridesetUp()andmovethebehavior.ThisfollowstheDRYprinciple,

Page 163: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

meaningDon’tRepeatYourself,andleadstomoremaintainablesoftware.Soatthetopofthetestmethod,wecreatethemockcontextandsetthecontextforthistestusingthesetContext()method;wecreatetheapplicationusingcreateApplication().YouneedtoensureyoucallsetContextbeforecreateApplicationasthisishowyougetthecorrectinstantiationorder.Now,thecodethatactuallytestsfortherequiredbehaviorsettingthedecimalplaces,retrievingit,andverifyingitsvalue.Thisisit,usingRenamingMockContexttogiveuscontroloverSharedPreferences.WhenevertheSharedPreferenceisrequested,themethodwillinvokethedelegatingcontext,addingtheprefixforthename.TheoriginalSharedPreferencesclassusedbytheapplicationareunchanged:

publicclassTemperatureConverterApplicationextendsApplication{

privatestaticfinalintDECIMAL_PLACES_DEFAULT=2;

privatestaticfinalStringKEY_DECIMAL_PLACES=".KEY_DECIMAL_PLACES";

privateSharedPreferencessharedPreferences;

@Override

publicvoidonCreate(){

super.onCreate();

sharedPreferences=

PreferenceManager.getDefaultSharedPreferences(this);

}

publicvoidsetDecimalPlaces(intplaces){

Editoreditor=sharedPreferences.edit();

editor.putInt(KEY_DECIMAL_PLACES,places);

editor.apply();

}

publicintgetDecimalPlaces(){

returnsharedPreferences.getInt(KEY_DECIMAL_PLACES,

DECIMAL_PLACES_DEFAULT);

}

}

WecanverifythatourtestsdonotaffecttheapplicationbyfurnishingtheTemperatureConverterApplicationclasswithsomevalueinthesharedpreferences,runningtheapplication,thenrunningthetestsandeventuallyverifyingthatthisvaluewasnotaffectedbyexecutingthetests.

Page 164: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingactivitiesThenextexampleshowshowanactivitycanbetestedincompleteisolationusingtheActivityUnitTestCase<Activity>baseclass.AsecondchoicewouldbeActivityInstrumentationTestCase2<Activity>.However,theformerallowsyoutocreateanActivitybutnotattachittothesystem,meaningyoucannotlaunchotherActivities(youareanActivitysingleunit).ThischoiceoftheparentclassnotonlyrequiresmorecareandattentioninyoursetupbutalsoprovidesagreaterflexibilityandcontrolovertheActivityundertest.ThiskindoftestisintendedtotestgeneralActivitybehaviorandnotanActivityinstance’sinteractionwithothersystemcomponentsoranyUI-relatedtests.

Firstthingsfirst,hereistheclassundertest.ItisasimpleActivitywithonebutton.Whenthisbuttonispressed,itfiresanIntenttostarttheDialerandfinishesitself:

publicclassForwardingActivityextendsActivity{

privatestaticfinalintGHOSTBUSTERS=999121212;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_forwarding);

Viewbutton=findViewById(R.id.forwarding_go_button);

button.setOnClickListener(newView.OnClickListener(){

@Override

publicvoidonClick(Viewv){

Intentintent=newIntent("tel:"+GHOSTBUSTERS);

startActivity(intent);

finish();

}

});

}

}

Forourtestcase,weextendActivityUnitTestCase<ForwardingActivity>,aswementionedearlier,asaunittestforanActivityclass.Thisactivityundertestwillbedisconnectedfromthesystem,soitisonlyintendedtotestinternalaspectsofitandnotitsinteractionwithothercomponents.InthesetUp()method,wecreatetheIntentthatwillstartourActivityundertest,thatis,ForwardingActivity.NotetheuseofgetInstrumentation().ThegetContextclass,asatthispointinthesetUp()methodoftheActivityContext,isstillnull:

publicclassForwardingActivityTestextends

ActivityUnitTestCase<ForwardingActivity>{

privateIntentstartIntent;

publicForwardingActivityTest(){

super(ForwardingActivity.class);

}

@Override

protectedvoidsetUp()throwsException{

super.setUp();

Page 165: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Contextcontext=getInstrumentation().getContext();

startIntent=newIntent(context,ForwardingActivity.class);

}

Nowthatthesetupisdone,wecanmoveontoourtests:

publicvoidtestLaunchingSubActivityFiresIntentAndFinishesSelf(){

Activityactivity=startActivity(startIntent,null,null);

Viewbutton=activity.findViewById(R.id.forwarding_go_button);

button.performClick();

assertNotNull(getStartedActivityIntent());

assertTrue(isFinishCalled());

}

ThefirsttestperformsaclickontheGobuttonoftheForwardingActivity.TheonClickListenerclassofthatbuttoninvokesstartActivity()withanIntentthatdefinesanewActivitythatwillbestarted.Afterperformingthisaction,weverifythattheIntentusedtolaunchthenewActivityisnotnull.ThegetStartedActivityIntent()methodreturnstheIntentthatwasusediftheActivityundertestsinvokedstartActivity(Intent)orstartActivityForResult(Intent,int).Next,weassertthatfinish()wascalled,andwedothatbyverifyingthereturnvalueofFinishCalled(),whichreturnstrueifoneofthefinishmethods(finish(),finishFromChild(Activity),orfinishActivity(int))wascalledintheActivityundertest:

publicvoidtestExampleOfLifeCycleCreation(){

Activityactivity=startActivity(startIntent,null,null);

//Atthispoint,onCreate()hasbeencalled,butnothingelse

//sowecompletethestartupoftheactivity

getInstrumentation().callActivityOnStart(activity);

getInstrumentation().callActivityOnResume(activity);

//Atthispointyoucouldtestforvariousconfigurationaspects

//oryoucoulduseaMockContext

//toconfirmthatyouractivityhasmade

//certaincallstothesystemandsetitselfupproperly.

getInstrumentation().callActivityOnPause(activity);

//Atthispointyoucouldconfirmthat

//theactivityhaspausedproperly,

//asifitisnolongerthetopmostactivityonscreen.

getInstrumentation().callActivityOnStop(activity);

//Atthispoint,youcouldconfirmthat

//theactivityhasshutitselfdownappropriately,

//oryoucoulduseaMockContexttoconfirmthat

//youractivityhasreleasedany

//systemresourcesitshouldnolongerbeholding.

Page 166: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

//ActivityUnitTestCase.tearDown()isalwaysautomaticallycalled

//andwilltakecareofcallingonDestroy().

}

Thesecondtestisperhapsthemoreinterestingtestmethodinthistestcase.ThistestcasedemonstrateshowtoexercisetheActivitylifecycle.AfterstartingtheActivity,onCreate()iscalledautomatically,andwecanthenexerciseotherlifecyclemethodsbyinvokingthemmanually.Tobeabletoinvokethesemethods,weuseIntrumentationofthistest.Also,wedon’tmanuallyinvokeonDestroy()asitwillbeinvokedforusintearDown().

Let’swalkthroughthecode.ThismethodstartstheActivityinthesamewayasthepreviouslyanalyzedtest.Aftertheactivityisstarted,itsonCreate()methodiscalledautomaticallybythesystem.WethenuseInstrumentationtoinvokeotherlifecyclemethodstocompletetheActivityunderteststartup.ThesecorrespondtoonStart()andonResume()intheActivitylifecycle.

TheActivityisnowcompletelystarted,andit’stimetotestfortheaspectsweareinterestedin.Oncethisisachieved,wecanfollowotherstepsinthelifecycle.Notethatthissampletestdoesnotassertanythingherebutsimplypointsouthowtostepthroughthelifecycle.Tofinishthelifecycle,wecallthroughtoonPause()andonStop().Asweknow,onDestroy()isavoidedasitwillautomaticallybecalledbytearDown().

Thistestrepresentsatestskeleton.YoucanreuseittotestyourActivitiesinisolationandtotestlifecycle-relatedcases.TheinjectionofmockobjectscanalsofacilitatetestingofotheraspectsoftheActivity,suchasaccessingsystemresources.

Page 167: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 168: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Testingfiles,databases,andcontentprovidersSometestcaseshavetheneedtoexercisedatabasesorContentProvideroperations,andsooncomestheneedtomocktheseoperations.Forexample,ifwearetestinganapplicationonarealdevice,wedon’twanttointerferewiththenormaloperationofapplicationsonthesaiddevice,especiallyifweweretochangevaluesthatmaybesharedbymorethanoneapplication.

Suchcasescantakeadvantageofanothermockclassthatisnotapartoftheandroid.test.mockpackagebutofandroid.testinstead,namelyRenamingDelegatingContext.

Remember,thisclassletsusmockfileanddatabaseoperations.Aprefixsuppliedintheconstructorisusedtomodifythetargetoftheseoperations.AllotheroperationsaredelegatedtothedelegatingContextthatyouspecify.

SupposeourActivityundertestusessomefilesordatabasesthatwewanttocontrolinsomeway,probablytointroducespecializedcontenttodriveourtests,andwedon’twantto,orwecannotusetherealfilesordatabase.Insuchcases,wecreateRenamingDelegatingContext,whichspecifiesaprefix.Weprovidemockfilesusingthisprefixandintroduceanycontentweneedtodriveourtests,andtheActivityundertestcouldusethemwithnoalteration.

TheadvantageofkeepingourActivityunchanged,thatis,notmodifyingittoreadfromadifferentsource,isthatthisassuresthatallthetestsarevalid.Ifweintroduceachangeonlyintendedforourtests,wewillnotbeabletoassurethat,underrealconditions,theActivitybehavesthesame.

Todemonstratethiscase,wewillcreateanextremelysimpleActivity.

TheMockContextExampleActivityactivitydisplaysthecontentofafileinsideTextView.WhatweintendtodemonstrateishowitdisplaysdifferentcontentduringanormaloperationofActivity,ascomparedtowhenitisundertest:

publicclassMockContextExampleActivityextendsActivity{

privatestaticfinalStringFILE_NAME="my_file.txt";

privateTextViewtextView;

@Override

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_mock_context_example);

textView=(TextView)findViewById(R.id.mock_text_view);

try{

FileInputStreamfis=openFileInput(FILE_NAME);

textView.setText(convertStreamToString(fis));

}catch(FileNotFoundExceptione){

Page 169: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

textView.setText("Filenotfound");

}

}

privateStringconvertStreamToString(java.io.InputStreamis){

Scanners=newScanner(is,"UTF-8").useDelimiter("\\A");

returns.hasNext()?s.next():"";

}

publicStringgetText(){

returntextView.getText().toString();

}

}

ThisisoursimpleActivity.Itreadsthecontentofthemy_file.txtfileanddisplaysitonTextView.Italsodisplaysanyerrorthatmightoccur.Obviously,inarealscenario,youwouldhavebettererrorhandlingthanthis.

Weneedsomecontentforthisfile.Probablytheeasiestwaytocreatethefilesisasshowninthefollowingcode:

$adbshell

$echo"Thisisrealdata">data/data/com.blundell.tut/files/my_file.txt

$echo"Thisis*MOCK*data">

/data/data/com.blundell.tut/files/test.my_file.txt

Wecreatedtwodifferentfiles,onenamedmy_file.txtandtheothertest.my_file.txt,withdifferentcontent.Thelatterindicatesthatitisamockcontent.Ifyourantheprecedingactivitynow,youwouldseeThisisrealdataasitisreadingfromtheexpectedfilemy_file.txt.

Thefollowingcodedemonstratestheuseofthismockdatainouractivitytests:

publicclassMockContextExampleTest

extendsActivityUnitTestCase<MockContextExampleActivity>{

privatestaticfinalStringPREFIX="test.";

privateRenamingDelegatingContextmockContext;

publicMockContextExampleTest(){

super(MockContextExampleActivity.class);

}

@Override

protectedvoidsetUp()throwsException{

super.setUp();

mockContext=new

RenamingDelegatingContext(getInstrumentation().getTargetContext(),PREFIX);

mockContext.makeExistingFilesAndDbsAccessible();

}

publicvoidtestSampleTextDisplayed(){

setActivityContext(mockContext);

Page 170: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

startActivity(newIntent(),null,null);

assertEquals("Thisis*MOCK*data\n",getActivity().getText());

}

}

TheMockContextExampleTestclassextendsActivityUnitTestCasebecausewearelookingforisolatedtestingofMockContextExampleActivityandbecausewearegoingtoinjectamockedcontext;inthiscase,theinjectedcontextisRenamingDelegatingContextasadependency.

Ourfixtureconsistsofthemockcontext,mockContextandRenamingDelegatingContext,usingthetargetcontextobtainedbygetInstrumentation().getTargetContext().NotethatthecontextwheretheinstrumentationisrunisdifferentthanthecontextoftheActivityundertest.

Hereafundamentalstepfollows—sincewewanttomaketheexistingfilesanddatabasesaccessibletothistest,wehavetoinvokemakeExistingFilesAndDbsAccessible().

Then,ourtestnamedtestSampleTextDisplayed()injectsthemockcontextusingsetActivityContext().

TipYoumustinvokesetActivityContext()toinjectamockcontextbeforeyoustarttheActivityundertestbyinvokingstartActivity().

Then,theActivityisstartedbystartActivity()usingablankIntentjustcreated.

WeobtainthetextvalueheldbytheTextViewbyusingagetterthatweaddedtotheActivity.Iwouldneverrecommendchangingproductioncode(thatis,exposinggetters)justforyourtestsinarealproject,asthiscanleadtobugs,incorrectusagepatternsbyotherdevelopers,andsecurityissues.However,here,wearedemonstratingtheuseofRenamingDelegatingContextratherthantestcorrectness.

Finally,thetextvalueobtainedischeckedagainsttheThisisMOCK*datastring.Itisimportantheretonoticethatthevalueusedforthistestisthetestfilecontentandnottherealfilecontent.

Page 171: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheBrowserProvidertestsThesetestsarebasedontheBrowsermoduleoftheAndroidOpenSourceProject(AOSP).TheAOSPhaslotsofgreattestexamples,andusingthemasanexampleherestopsyoufromwritingalotofboilerplatecodetosetupthescenarioforthetest.TheyareintendedtotestsomeaspectsoftheBrowserbookmarks,contentprovider,whichispartofthestandardBrowserincludedwiththeAndroidplatform(nottheChromeappbutthedefaultBrowserapp):

publicclassBrowserProviderTestsextendsAndroidTestCase{

privateList<Uri>deleteUris;

@Override

protectedvoidsetUp()throwsException{

super.setUp();

deleteUris=newArrayList<Uri>();

}

@Override

protectedvoidtearDown()throwsException{

for(Uriuri:deleteUris){

deleteUri(uri);

}

super.tearDown();

}

}

NoteAOSPtestsarenotavailablefromtheexampleprojectwiththischapterbutareavailableonlineathttps://github.com/android/platform_packages_apps_browser/blob/master/tests/src/com/android/browser/BrowserProviderTests.java

ThissnippetincludesthetestcasedefinitionthatextendsAndroidTestCase.TheBrowserProviderTestsclassextendsAndroidTestCasebecauseaContextisneededtoaccesstheprovidercontent.

ThefixturecreatedinthesetUp()methodcreatesalistofUristhatareusedtokeeptrackoftheinsertedUristobedeletedattheendofeachtestinthetearDown()method.Thedeveloperscouldhavesavedthishassleusingamockcontentprovider,maintainingtheisolationbetweenourtestsandthesystem.Anyway,tearDown()iteratesoverthislistanddeletesthestoredUris.ThereisnoneedtooverridetheconstructorhereasAndroidTestCaseisnotaparameterizedclass,andwedon’tneedtodoanythingspecialinit.

Nowcomesthetest:

publicvoidtestHasDefaultBookmarks(){

Cursorc=getBookmarksSuggest("");

try{

assertTrue("Nodefaultbookmarks",c.getCount()>0);

}finally{

Page 172: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

c.close();

}

}

ThetestHasDefaultBookmarks()methodisatesttoensurethatthereareanumberofdefaultbookmarksalwayspresentinthedatabase.Onstartup,acursoriteratesoverthedefaultbookmarksobtainedbyinvokinggetBookmarksSuggest(""),whichreturnsanunfilteredcursorofbookmarks;thisiswhythecontentproviderqueryparameteris"":

publicvoidtestPartialFirstTitleWord(){

assertInsertQuery(

"http://www.example.com/rasdfe","nfgjrasdfywe","nfgj");

}

ThetestPartialFirstTitleWord()methodandthreeotherslikeitnotshownheretestFullFirstTitleWord(),testFullFirstTitleWordPartialSecond(),andtestFullTitle()testfortheinsertionofbookmarks.Toachievethis,theyinvokeassertInsertQuery()usingthebookmarkedURL,itstitle,andthequery.ThemethodassertInsertQuery()addsthebookmarkstothebookmarkprovider,insertingtheURLissuedasaparameterwiththespecifiedtitle.TheUrireturnedisverifiedtobenotnullandnotexactlythesameasthedefaultone.Finally,theUriisinsertedinthelistofUriinstancestobedeletedintearDown().Thecodeforthiscanbeseenintheutilitymethodsshownasfollows:

publicvoidtestFullTitleJapanese(){

Stringtitle="\u30ae\u30e3\u30e9\u30ea\u30fc\u30fcGoogle\u691c\u7d22";

assertInsertQuery("http://www.example.com/sdaga",title,title);

}

NoteUnicodeisacomputingindustrystandarddesignedtoconsistentlyanduniquelyencodecharactersusedinwrittenlanguagesthroughouttheworld.TheUnicodestandarduseshexadecimalstoexpressacharacter.Forexample,thevalue\u30aerepresentstheKatakanaletterGI().

WehaveseveralteststhatareintendedtoverifytheutilizationofthisbookmarkproviderforlocalesandlanguagesotherthanjustEnglish.TheseparticularcasescovertheJapaneselanguageutilizationinbookmarktitles.TheteststestFullTitleJapanese(),andtwoothersthatarenotshownhere,thatis,testPartialTitleJapanese()andtestSoundmarkTitleJapanese()aretheJapaneseversionsofthetestsintroducedbeforeusingUnicodecharacters.Itisrecommendedtotesttheapplication’scomponentsunderdifferentconditions,likeinthiscase,whereotherlanguageswithdifferentcharactersetsareused.

Severalutilitymethodsfollow.Thesearetheutilitiesusedinthetests.WebrieflylookedatassertInsertQuery()before,sonow,let’slookattheothermethodsaswell:

privatevoidassertInsertQuery(Stringurl,Stringtitle,Stringquery){

addBookmark(url,title);

assertQueryReturns(url,title,query);

}

Page 173: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

privatevoidaddBookmark(Stringurl,Stringtitle){

Uriuri=insertBookmark(url,title);

assertNotNull(uri);

assertFalse(BOOKMARKS_URI.equals(uri));

deleteUris.add(uri);

}

privateUriinsertBookmark(Stringurl,Stringtitle){

ContentValuesvalues=newContentValues();

values.put("title",title);

values.put("url",url);

values.put("visits",0);

values.put("date",0);

values.put("created",0);

values.put("bookmark",1);

returngetContext().getContentResolver().insert(BOOKMARKS_URI,

values);

}

privatevoidassertQueryReturns(Stringurl,Stringtitle,Stringquery){

Cursorc=getBookmarksSuggest(query);

try{

assertTrue(title+"notmatchedby"+query,c.getCount()>0);

assertTrue("Morethanoneresultfor"+query,c.getCount()==1);

while(c.moveToNext()){

Stringtext1=getCol(c,SearchManager.SUGGEST_COLUMN_TEXT_1);

assertNotNull(text1);

assertEquals("Badtitle",title,text1);

Stringtext2=getCol(c,SearchManager.SUGGEST_COLUMN_TEXT_2);

assertNotNull(text2);

Stringdata=getCol(c,SearchManager.SUGGEST_COLUMN_INTENT_DATA);

assertNotNull(data);

assertEquals("BadURL",url,data);

}

}finally{

c.close();

}

}

privateStringgetCol(Cursorc,Stringname){

intcol=c.getColumnIndex(name);

Stringmsg="Column"+name+"notfound,"

+"columns:"+Arrays.toString(c.getColumnNames());

assertTrue(msg,col>=0);

returnc.getString(col);

}

privateCursorgetBookmarksSuggest(Stringquery){

UrisuggestUri=

Uri.parse("content://browser/bookmarks/search_suggest_query");

String[]selectionArgs={query};

Cursorc=getContext().getContentResolver().query(suggestUri,null,"url

LIKE?",selectionArgs,null);

assertNotNull(c);

returnc;

}

Page 174: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

privatevoiddeleteUri(Uriuri){

intcount=getContext().getContentResolver().delete(uri,null,null);

assertEquals("Failedtodelete"+uri,1,count);

}

ThemethodassertInsertQuery()invokesassertQueryReturns(url,title,andquery),afteraddBookmark(),toverifythattheCursorreturnedbygetBookmarksSuggest(query)containstheexpecteddata.Thisexpectationcanbesummarizedas:

Thenumberofrowsreturnedbythequeryisgreaterthan0Thenumberofrowsreturnedbythequeryisequalto1ThetitleinthereturnedrowisnotnullThetitlereturnedbythequeryisexactlythesameasthemethodparameterThesecondlineforthesuggestionisnotnullTheURLreturnedbythequeryisnotnullThisURLmatchesexactlytheURLissuedasthemethodparameter

Thisstrategyprovidesaninterestingpatterntofollowinourtests.Someoftheutilitymethodsthatweneedtocreatetocompleteourtestscanalsocarrytheirownverificationofseveralconditionsandimproveourtestquality.

Creatingassertmethodsinourclassesallowsustointroduceadomain-specifictestinglanguagethatcanbereusedwhentestingotherpartsofthesystem.

Page 175: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 176: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingexceptionsWehavementionedthisbeforeinChapter1,GettingStartedwithTesting,wherewestatedthatyoushouldtestforexceptionsandwrongvaluesinsteadofjusttestingpositivecases:

@Test(expected=InvalidTemperatureException.class)

publicfinalvoidtestExceptionForLessThanAbsoluteZeroF(){

TemperatureConverter.

fahrenheitToCelsius(TemperatureConverter.ABSOLUTE_ZERO_F-1);

}

@Test(expected=InvalidTemperatureException.class)

publicfinalvoidtestExceptionForLessThanAbsoluteZeroC(){

TemperatureConverter.

celsiusToFahrenheit(TemperatureConverter.ABSOLUTE_ZERO_C-1);

}

Wehavealsopresentedthesetestsbefore,buthere,wearediggingdeeperintoit.ThefirstthingtonoticeisthattheseareJUnit4tests,meaningwecantestforexceptionsusingtheexpectedannotationparameter.Whenyoudownloadthechapter’ssampleproject,youwillbeabletoseethatitissplitintotwomodules,oneofthembeingcore,whichisapureJavamodule,andso,wehavethechancetouseJUnit4.Atthetimeofwritingthis,AndroidhasannouncedJUnit4supportbutnotyetreleasedit,sowearestillonJUnit3forInstrumentedAndroidtests.

Everytimewehaveamethodthatissupposedtogenerateanexception,weshouldtestthisexceptionalcondition.ThebestwayofdoingitisbyusingJUnit4’sexpectedparameter.Thisdeclaresthatthetestshouldthrowtheexception,ifitdoesnotthrowtheexceptionorthrowsadifferentexception,thetestwillfail.ThiscanalsobedoneinJUnit3byinvokingthemethodundertestinsideatry-catchblock,catchingtheexpectedexception,andfailingotherwise:

publicvoidtestExceptionForLessThanAbsoluteZeroC(){

try{

TemperatureConverter.celsiusToFahrenheit(ABSOLUTE_ZERO_C-1);

fail();

}catch(InvalidTemperatureExceptionex){

//donothingweexpectthisexception!

}

}

Page 177: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 178: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestinglocalandremoteservicesWhenyouwanttotestanandroid.app.Service,theideaistoextendtheServiceTestCase<Service>classtotestinacontrolledenvironment:

publicclassDummyServiceTestextendsServiceTestCase<DummyService>{

publicDummyServiceTest(){

super(DummyService.class);

}

publicvoidtestBasicStartup(){

IntentstartIntent=newIntent();

startIntent.setClass(getContext(),DummyService.class);

startService(startIntent);

}

publicvoidtestBindable(){

IntentstartIntent=newIntent();

startIntent.setClass(getContext(),DummyService.class);

bindService(startIntent);

}

}

Theconstructor,asinothersimilarcases,invokestheparentconstructorthatpassestheAndroidserviceclassasaparameter.

ThisisfollowedbytestBasicStartup().WestarttheserviceusinganIntentthatwecreatehere,settingitsclasstotheclassoftheserviceundertest.WealsousetheinstrumentedContextforthisIntent.Thisclassallowsforsomedependencyinjection,aseveryservicedependsontheContextinwhichitruns,andtheapplicationwithwhichitisassociated.Thisframeworkallowsyoutoinjectmodified,mock,orisolatedreplacementsforthesedependencies,andthusperformsatrueunittest.

NoteDependencyInjection(DI)isasoftwaredesignpatternthatdealswithhowcomponentsgetholdoftheirdependencies.Youcandothisyourselfmanuallyoruseoneofthemanydependencyinjectionlibraries.

Sincewesimplyrunourtestsasis,theservicewillbeinjectedwithafullyfunctionalContextandagenericMockApplicationobject.Then,westarttheserviceusingthestartService(startIntent)method,inthesamewayasifitwerestartedbyContext.startService(),providingtheargumentsitsupplied.Ifyouusethismethodtostarttheservice,itwillautomaticallybestoppedbytearDown().

Anothertest,testBindable(),willtestwhethertheservicecanbebound.ThistestusesbindService(startIntent),whichstartstheserviceundertestinthesamewayasifitwerestartedbyContext.bindService(),providingtheargumentsitsupplied.Itreturnsthecommunicationchanneltotheservice.Itmayreturnnullifclientscannotbindtotheservice.Mostprobably,thistestshouldcheckforthenullreturnvalueintheservicewithanassertionlikeassertNotNull(service)toverifythattheservicewasboundcorrectly,

Page 179: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

butitdoesn’t,sowecanfocusontheframeworkclassesinuse.Besuretoincludethistestwhenyouwritecodeforsimilarcases.

ThereturnedIBinderisusuallyforacomplexinterfacethathasbeendescribedusingAIDL.Inordertotestwiththisinterface,yourservicemustimplementagetService()method,asshowninDummServiceintheexampleprojectforthischapter;whichhasthisimplementationofthatmethod:

publicclassLocalBinderextendsBinder{

DummyServicegetService(){

returnDummyService.this;

}

}

Page 180: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 181: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ExtensiveuseofmockobjectsInthepreviouschapters,wedescribedandusedthemockclassesthatarepresentintheAndroidSDK.Whiletheseclassescancoveragreatnumberofcases,thereareotherAndroidclassesandyourowndomainclassestoconsider.Youmighthavetheneedforothermockobjectstofurnishyourtestcases.

Severallibrariesprovidetheinfrastructuretosatisfyourmockingneeds,butwearenowconcentratingonMockito,whichisperhapsthemostwidelyusedlibraryinAndroid.

NoteThisisnotaMockitotutorial.WewilljustbeanalyzingitsuseinAndroid,soifyouarenotfamiliarwithit,Iwouldrecommendthatyoutakealookatthedocumentationavailableonitswebsiteathttps://code.google.com/p/mockito/.

MockitoisanopensourcesoftwareprojectavailableundertheMITlicense,andprovidestestdoubles(mockobjects).ItisaperfectmatchforTest-drivenDevelopmentduetothewayitverifiesexpectationsandduetoitsdynamicallygeneratedmockobjectsbecausetheysupportrefactoring,andthetestcodewillnotbreakwhenrenamingmethodsorchangingitssignature.

Summarizingitsdocumentation,themostrelevantbenefitsofMockitoareasfollows:

AskquestionsaboutinteractionsafterexecutionItisnotexpect-run-verify–avoidsexpensivesetupOnewaytomockthatisasimpleAPIEasyrefactoringwithtypesusedItmocksconcreteclassesaswellasinterfaces

Todemonstrateitsusageandtoestablishastylethatcanbelaterreproducedforothertests,wearecompletingsomeexampletestcases.

NoteThelatestversionofMockitosupportedbyAndroidasofthiswritingisDexmakerMockito1.1.Youmightwanttotryoutadifferentone,butyouwillmostprobablyencounterproblems.

ThefirstthingweshoulddoisaddMockitoasadependencyforyourAndroidinstrumentationtests.ThisisassimpleasaddingtheandroidTestCompilereferencetoyourdependenciesclosure.Gradlewilldotherest,thatis,downloadtheJARfileandaddittoyourclasspath:

dependencies{

//othercompiledependencies

androidTestCompile('com.google.dexmaker:dexmaker-mockito:1.1')

}

InordertouseMockitoinourtests,weonlyneedtostaticallyimportitsmethodsfrom

Page 182: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

org.mockito.Usually,yourIDEwillgiveyoutheoptiontostaticallyimportthese,butifitdoesnot,youcantrytoaddthemmanually(ifthecodeisredwhenmanuallyadded,thenyouhaveaproblemwiththelibrarybeingavailable):

importstaticorg.mockito.Matchers.*;

importstaticorg.mockito.Mockito.*;

Itispreferabletousespecificimportsinsteadofusingthewildcard.Thewildcardsareherejustforbrevity.ItismostlikelythatwhenyourIDEautosaves,itwillexpandthemintotheimportsneeded(orremovethemifyouaren’tusingthem!).

Page 183: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ImportinglibrariesWehaveaddedtheMockitolibrarytotheproject’sJavaBuildPath.Usually,thisisnotaproblem,butsometimes,rebuildingtheprojectleadsustothefollowingerrorthatstopstheprojectbeingbuilt:Error:duplicatefilesduringpackagingofAPK.

Thisdependsonhowmanylibrariesareincludedbytheprojectandwhattheyare.

MostoftheavailableopensourcelibrarieshaveasimilarcontentasproposedbyGNUandincludefilessuchasLICENSE,NOTICE,CHANGES,COPYRIGHT,andINSTALL,amongothers.WewillfindthisproblemassoonaswetrytoincludemorethanoneinthesameprojecttoultimatelybuildasingleAPK.Thiscanberesolvedinyourbuild.gradle:

packagingOptions{

exclude'META-INF/LICENSE'

exclude'folder/duplicatedFileName'

}

Page 184: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MockitousageexampleLet’screateEditText,whichonlyacceptssigneddecimalnumbers.We’llcallitEditNumber.EditNumberusesInputFiltertoprovidethisfeature.Inthefollowingtests,wewillbeexercisingthisfiltertoverifythatthecorrectbehaviorisimplemented.

Tocreatethetest,wewillbeusingapropertythatEditNumberinheritsfromEditText,soitcanaddalistener,actuallyaTextWatcher.ThiswillprovidemethodsthatarecalledwheneverthetextofEditNumberchanges.ThisTextWatcherisacollaboratorforthetest,andwecouldhaveimplementeditasitsownseparateclassandverifiedtheresultsofcallingitsmethods,butthisistedious,andmightintroducemoreerrors,sotheapproachtakenistouseMockitoinordertoavoidtheneedofwritinganexternalTextWatcher.

ThisispreciselyhowweareintroducingamockTextWatchertocheckmethodinvocationswhenthetextchanges.

Page 185: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheEditNumberfiltertestsThissuiteoftestswillexerciseInputFilterbehaviorofEditNumber,checkingthemethodcallsontheTextWatchermockandverifyingtheresults.

WeareusinganAndroidTestCasebecauseweareinterestedintestingEditNumberinisolationofothercomponentsorActivities.

Wehaveseveralinputsthatneedtobetested(weallowdecimalnumbers,butdonotallowmultipledecimals,letters,andsoon),andsowecanhaveonetestwithanarrayofexpectedinputandanarrayofexpectedoutput.However,thetestcangetverycomplicatedandwouldbeawfultomaintain.AbetterapproachistohaveonetestforeachtestcaseofInputFilter.Thisallowsustogivemeaningfulnamestoourtestsandanexplanationofwhatweareaimingtotest.Wewillfinishupwithalistlikethis:

testTextChangedFilter*

*WorksForBlankInput

*WorksForSingleDigitInput

*WorksForMultipleDigitInput

*WorksForZeroInput

*WorksForDecimalInput

*WorksForNegativeInput

*WorksForDashedInput

*WorksForPositiveInput

*WorksForCharacterInput

*WorksForDoubleDecimalInput

Now,wewillrunthroughtheuseofmocksforoneoftheseteststestTextChangedFilterWorksForCharacterInput(),andifyouchecktheexampleproject,youwillseethatalltheothertestsfollowthesamepattern,andwehaveactuallyextractedoutahelpermethodthatactsasacustomassertionforalltests:

publicvoidtestTextChangedFilterWorksForCharacterInput(){

assertEditNumberTextChangeFilter("A1A","1");

}

/**

*@paraminputthetexttobefiltered

*@paramoutputtheresultyouexpectoncetheinputhasbeenfiltered

*/

privatevoidassertEditNumberTextChangeFilter(Stringinput,Stringoutput)

{

intlengthAfter=output.length();

TextWatchermockTextWatcher=mock(TextWatcher.class);

editNumber.addTextChangedListener(mockTextWatcher);

editNumber.setText(input);

verify(mockTextWatcher)

.afterTextChanged(editableCharSequenceEq(output));

verify(mockTextWatcher)

.onTextChanged(charSequenceEq(output),eq(0),eq(0),eq(lengthAfter));

verify(mockTextWatcher)

.beforeTextChanged(charSequenceEq(""),eq(0),eq(0),eq(lengthAfter));

Page 186: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

}

Asyoucansee,thetextcaseisprettystraightforward;itassertsthatwhenyouenterA1AintothetextoftheEditNumberview,thetextisactuallychangedinto1.ThismeansthatourEditNumberhasfilteredoutthecharacters.AninterestingthinghappenswhenwelookattheassertEditNumberTextChangeFilter(input,output)helpermethod.WithinourhelpermethodiswhereweverifythattheInputFilterisdoingitsjobanditishereweuseMockito.TherearefourcommonstepstotakewhenusingMockitomockobjects:

1. Instantiatetheintendedmocksthatarereadyforuse.2. Determinewhatbehaviorisexpectedandstubittoreturnanyfixturedata.3. Exercisethemethods,usuallybyinvokingmethodsoftheclassundertest.4. Verifythebehaviorofyourmockobjecttopassthetest.

Accordingtostepone,wecreateamockTextWatcherusingmock(TextWatcher.class)andsetitasourTextChangedListeneronEditNumber.

Weskipsteptwointhisinstanceaswehavenofixturedata,inthattheclasswearemockingdoesnothaveanymethodsthatareexpectedtoreturnavalue.We’llcomebacktothisinanothertestlateron.

Instepthree,wehaveourmockinplace,andwecanexercisethemethodundertesttoperformitsintendedaction.Inourcase,themethodiseditNumber.setText(input),andtheintendedactionistosetthetextandthuspromptourInputFiltertorun.

Stepfouriswhereweverifythatthetextwasactuallychangedbyourfilter.Let’sbreakstepfourdownalittle.Hereareourverificationsagain:

verify(mockTextWatcher)

.afterTextChanged(editableCharSequenceEq(output));

verify(mockTextWatcher)

.onTextChanged(charSequenceEq(output),eq(0),eq(0),eq(lengthAfter));

verify(mockTextWatcher)

.beforeTextChanged(charSequenceEq(""),eq(0),eq(0),eq(lengthAfter));

Wewillbeusingtwocustomwrittenmatchers(editableCharSequenceEq(String)andcharSequenceEq(String))becauseweareinterestedincomparingthestringcontentfordifferentclassesusedbyAndroid,suchasEditableandCharSequence.Whenyouuseaspecialmatcher,itmeansallcomparisonsdoneforthatverificationmethodcallneedaspecialwrappermethod.

Theothermatcher,eq(),expectsintthatisequaltothegivenvalue.ThelatterisprovidedbyMockitoforallprimitivetypesandobjects,butweneedtoimplementeditableCharSequenceEq()andcharSequenceEq()asitisanAndroid-specificmatcher.

MockitohasapredefinedArgumentMatcherthatwouldhelpuscreateourmatcher.Youextendtheclassanditgivesyouonemethodtooverride:

abstractbooleanmatches(Tt);

Thematchesargumentmatchermethodexpectsanargumentthatyoucanusetocompare

Page 187: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

againstapredefinedvariable.Thisargumentisthe“actual”resultofyourmethodinvocation,andthepredefinedvariableisthe“expected”one.Youthendecidetoreturntrueorfalsewhethertheyarethesameornot.

Asyoumighthavealreadyrealized,thecustomArgumentMatcherclass’sfrequentuseinatestcouldbecomereallycomplexandmightleadtoerrors,sotosimplifythisprocess,wewillbeusingahelperclassthatwecallCharSequenceMatcher.WealsohaveEditableCharSequenceMatcher,whichcanbefoundintheexampleprojectofthischapter:

classCharSequenceMatcherextendsArgumentMatcher<CharSequence>{

privatefinalCharSequenceexpected;

staticCharSequencecharSequenceEq(CharSequenceexpected){

returnargThat(newCharSequenceMatcher(expected));

}

CharSequenceMatcher(CharSequenceexpected){

this.expected=expected;

}

@Override

publicbooleanmatches(Objectactual){

returnexpected.toString().equals(actual.toString());

}

@Override

publicvoiddescribeTo(Descriptiondescription){

description.appendText(expected.toString());

}

}

Weimplementmatchesbyreturningtheresultofthecomparisonoftheobjectpassedasargumentswithourpredefinedfieldaftertheyareconvertedtoastring.

WealsooverridethedescribeTomethod,andthisallowsustochangetheerrormessagewhentheverificationfails.Thisisalwaysagoodtiptoremember:takealookattheerrormessagesbeforeandafterdoingthis:

Argument(s)aredifferent!Wanted:

textWatcher.afterTextChanged(<Editablecharsequencematcher>);

Actualinvocationhasdifferentarguments:

textWatcher.afterTextChanged(1);

Argument(s)aredifferent!Wanted:

textWatcher.afterTextChanged(1XX);

Actualinvocationhasdifferentarguments:

textWatcher.afterTextChanged(1);

Whenthestaticinstantiationmethodforourmatcherisusedandweimportthisasastaticmethod,inourtest,wecansimplywrite:

verify(mockTextWatcher).onTextChanged(charSequenceEq(output),…

Page 188: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 189: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingviewsinisolationThetestthatweareanalyzinghereisbasedontheFocus2AndroidTestfromtheAndroidSDKApiDemosproject.ItdemonstrateshowsomepropertiesoftheViewsthatconformtoalayoutcanbetestedwhenthebehavioritselfcannotbeisolated.Thetestingfocusabilityofaviewisoneofthesesituations.

Weareonlytestingindividualviews.InordertoavoidcreatingthefullActivity,thistestextendsAndroidTestCase.YoumayhavethoughtaboutusingjustTestCase,butunfortunately,thisisnotpossibleasweneedaContexttoinflatetheXMLlayoutviaLayoutInflater,andAndroidTestCasewillprovideuswiththiscomponent:

publicclassFocusTestextendsAndroidTestCase{

privateFocusFinderfocusFinder;

privateViewGrouplayout;

privateButtonleftButton;

privateButtoncenterButton;

privateButtonrightButton;

@Override

protectedvoidsetUp()throwsException{

super.setUp();

focusFinder=FocusFinder.getInstance();

//inflatethelayout

Contextcontext=getContext();

LayoutInflaterinflater=LayoutInflater.from(context);

layout=(ViewGroup)inflater.inflate(R.layout.view_focus,null);

//manuallymeasureit,andlayitout

layout.measure(500,500);

layout.layout(0,0,500,500);

leftButton=(Button)layout.findViewById(R.id.focus_left_button);

centerButton=(Button)layout.findViewById(R.id.focus_center_button);

rightButton=(Button)layout.findViewById(R.id.focus_right_button);

}

Thesetuppreparesourtestasfollows:

1. WerequestaFocusFinderclass.ThisisaclassthatprovidesthealgorithmusedtofindthenextfocusableView.Itimplementsthesingletonpatternandthat’swhyweuseFocusFinder.getInstance()toobtainareferencetoit.Thisclasshasseveralmethodstohelpusfindfocusableandtouchableitems,givenvariousconditionsasthenearestinagivendirectionorsearchingfromaparticularrectangle.

2. Then,wegettheLayoutInflaterclassandinflatethelayoutundertest.Onethingweneedtotakeintoaccount,asourtestisisolatedfromotherpartsofthesystem,isthatwehavetomanuallymeasureandlayoutthecomponents.

3. Then,weusethefindviewspatternandassignthefoundviewstothefields.

Page 190: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Inapreviouschapter,weenumeratedalltheavailableassertsinourarsenal,andyoumayrememberthattotestaView’sposition,wehadacompletesetofassertionsintheViewAssertsclass.However,thisdependsonhowthelayoutisdefined:

publicvoidtestGoingRightFromLeftButtonJumpsOverCenterToRight(){

ViewactualNextButton=

focusFinder.findNextFocus(layout,leftButton,View.FOCUS_RIGHT);

Stringmsg="rightshouldbenextfocusfromleft";

assertEquals(msg,this.rightButton,actualNextButton);

}

publicvoidtestGoingLeftFromRightButtonGoesToCenter(){

ViewactualNextButton=

focusFinder.findNextFocus(layout,rightButton,View.FOCUS_LEFT);

Stringmsg="centershouldbenextfocusfromright";

assertEquals(msg,this.centerButton,actualNextButton);

}

ThemethodtestGoingRightFromLeftButtonJumpsOverCenterToRight(),asitsnamesuggests,teststhefocusgainedbytherightbuttonwhenthefocusmovesfromthelefttotherightbutton.Toachievethissearch,theinstanceofFocusFinderobtainedduringthesetUp()methodisemployed.ThisclasshasafindNextFocus()methodtoobtaintheViewthatreceivesfocusinagivendirection.Thevalueobtainedischeckedagainstourexpectations.

Inasimilarway,thetestGoingLeftFromRightButtonGoesToCenter()testteststhefocusthatgoesintheotherdirection.

Page 191: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 192: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingparsersTherearemanyoccasionswhereyourAndroidapplicationreliesonexternalXML,JSONmessages,ordocumentsobtainedfromwebservices.Thesedocumentsareusedfordatainterchangebetweenthelocalapplicationandtheserver.TherearemanyusecaseswhereXMLorJSONdocumentsareobtainedfromtheserverorgeneratedbythelocalapplicationtobesenttotheserver.Ideally,methodsinvokedbytheseactivitieshavetobetestedinisolationtohaverealunittests,andtoachievethis,weneedtoincludesomemockfilessomewhereinourAPKtorunthetests.

Butthequestioniswherecanweincludethesefiles?

Let’sfindout.

Page 193: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AndroidassetsTobegin,abriefreviewoftheassets’definitioncanbefoundintheAndroidSDKdocumentation:

Thedifferencebetween“resources”and“assets”isn’tmuchonthesurface,butingeneral,you’lluseresourcestostoreyourexternalcontentmuchmoreoftenthanyou’lluseassets.TherealdifferenceisthatanythingplacedintheresourcesdirectorywillbeeasilyaccessiblefromyourapplicationfromtheRclass,whichiscompiledbyAndroid.Whereas,anythingplacedintheassetsdirectorywillmaintainitsrawfileformatand,inordertoreadit,youmustusetheAssetManagertoreadthefileasastreamofbytes.Sokeepingfilesanddatainresources(res/)makesthemeasilyaccessible.

Clearly,assetsarewhatweneedtostorethefilesthatwillbeparsedtotesttheparser.

SoourXMLorJSONfilesshouldbeplacedintheassetsfoldertopreventmanipulationatcompiletimeandtobeabletoaccesstherawcontentwhiletheapplicationortestsarerun.

Butbecareful,weneedtoplacethemintheassetsofourandroidTestfolderbecausethen,thesearenotpartoftheapplication,andwedon’twantthempackedwithourcodewhenwereleasealiveapplication.

Page 194: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 195: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheparsertestThistestimplementsanAndroidTestCaseasallweneedisaContexttobeabletoreferenceourassetsfolder.Also,wehavewrittentheparsinginsideofthetest,asthepointofthistestisnothowtoparsexmlbuthowtoreferencemockassetsfromyourtests:

publicclassParserExampleActivityTestextendsAndroidTestCase{

publicvoidtestParseXml()throwsIOException{

InputStreamassetsXml=getContext().getAssets()

.open("my_document.xml");

Stringresult=parseXml(assetsXml);

assertNotNull(result);

}

}

}

TheInputStreamclassisobtainedbyopeningthemy_document.xmlfilefromtheassetsbygetContext().getAssets().NotethattheContextandthustheassetsobtainedherearefromthetestspackageandnotfromtheActivityundertest.

Next,theparseXml()methodisinvokedusingtherecentlyobtainedInputStream.IfthereisanIOException,thetestwillfailandspitouttheerrorfromthestacktrace,andifeverythinggoeswell,wetestthattheresultisnotnull.

WeshouldthenprovidetheXMLwewanttouseforthetestinanassetnamedmy_document.xml.Youwanttheassettobeunderthetestprojectfolder;bydefault,thisisandroidTest/assets.

Thecontentcouldbe:

<?xmlversion="1.0"encoding="UTF-8"?>

<records>

<record>

<name>Paul</name>

</record>

</records>

Page 196: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 197: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingformemoryusageSometimes,memoryconsumptionisanimportantfactortomeasurethegoodbehaviorofthetesttarget,beitanActivity,Service,ContentProvider,oranothercomponent.

Totestforthiscondition,wecanuseautilitytestthatyoucaninvokefromothertestsmainlyafterhavingrunatestloop:

publicvoidassertNotInLowMemoryCondition(){

//Verification:checkifitisinlowmemory

ActivityManager.MemoryInfomi=newActivityManager.MemoryInfo();

((ActivityManager)getActivity()

.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(mi);

assertFalse("Lowmemorycondition",mi.lowMemory);

}

Thisassertioncanbecalledfromothertests.Atthebeginning,itobtainsMemoryInfofromActivityManagerusinggetMemoryInfo(),aftergettingtheinstanceusinggetSystemService().ThelowMemoryfieldissettotrueifthesystemconsidersitselftocurrentlybeinalowmemorysituation.

Insomecases,wewanttodiveevendeeperintotheresourceusageandcanobtainmoredetailedinformationfromtheprocesstable.

Wecancreateanotherhelpermethodtoobtainprocessinformationanduseitinourtests:

privateStringcaptureProcessInfo(){

InputStreamin=null;

try{

Stringcmd="ps";

Processp=Runtime.getRuntime().exec(cmd);

in=p.getInputStream();

Scannerscanner=newScanner(in);

scanner.useDelimiter("\\A");

returnscanner.hasNext()?scanner.next():"scannererror";

}catch(IOExceptione){

fail(e.getLocalizedMessage());

}finally{

if(in!=null){

try{

in.close();

}catch(IOExceptionignore){

}

}

}

return"captureProcessInfoerror";

}

Toobtainthisinformation,acommand(inthiscase,psisused,butyoucanadaptittoyourneeds)isexecutedusingRuntime.exec().Theoutputofthiscommandisconcatenatedinastringthatislaterreturned.Wecanusethereturnvaluetoprintittothelogsinourtest,orwecanfurtherprocessthecontenttoobtainsummaryinformation.

Thisisanexampleofloggingtheoutput:

Page 198: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Log.d(TAG,captureProcessInfo());

Whenthistestisrun,weobtaininformationabouttherunningprocesses:

D/ActivityTest(1):USERPIDPPIDVSIZERSSWCHANPCNAME

D/ActivityTest(1):root10312220c009b74c0000ca4cS

/init

D/ActivityTest(1):root2000c004e72c00000000S

kthreadd

D/ActivityTest(1):root3200c003fdc800000000S

ksoftirqd/0

D/ActivityTest(1):root4200c004b2c400000000S

events/0

D/ActivityTest(1):root5200c004b2c400000000S

khelper

D/ActivityTest(1):root6200c004b2c400000000S

suspend

D/ActivityTest(1):root7200c004b2c400000000S

kblockd/0

D/ActivityTest(1):root8200c004b2c400000000S

cqueue

D/ActivityTest(1):root9200c018179c00000000S

kseriod

Theoutputwascutforbrevity,butifyourunit,youwillgetthecompletelistofprocessesthatrunonthesystem.

Abriefexplanationoftheinformationobtainedisasfollows:

Column Description

USER ThisisthetextualuserID.

PID ThisistheprocessIDnumberoftheprocess.

PPID ThisistheparentprocessID.

VSIZE ThisisthevirtualmemorysizeoftheprocessinKB.Thisisthevirtualmemorytheprocessreserves.

RSSThisistheresidentsetsize,thenon-swappedphysicalmemorythatataskhasused(inpages).Thisistheactualamountofrealmemorytheprocesstakesinpages.

Thisdoesnotincludepagesthathavenotbeendemand-loadedin.

WCHAN Thisisthe“channel”inwhichtheprocessiswaiting.Itistheaddressofasystemcall,andcanbelookedupinanamelistifyouneedatextualname.

PC ThisisthecurrentEIP(instructionpointer).

State(noheader)

Thisdenotestheprocessstates,whichareasfollows:

SisusedtoindicatesleepinginaninterruptiblestateRisusedtoindicaterunningTisusedtoindicateastoppedprocessZisusedtoindicateazombie

Column Description

Page 199: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

NAME Thisdenotesthecommandname.TheapplicationprocessesinAndroidarerenamedafteritspackagename.

Page 200: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 201: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingwithEspressoTestingUIcomponentscanbedifficult.Knowingwhenaviewhasbeeninflatedorensuringyoudon’taccessviewsonthewrongthreadcanleadtostrangebehaviorandflakytests.ThisiswhyGooglehasreleasedahelperlibraryforUI-relatedinstrumentationtestscalledEspresso(https://code.google.com/p/android-test-kit/wiki/Espresso).

AddingtheEspressolibraryJARcanbeachievedbyaddingtothe/libsfolder,buttomakeiteasierforGradleusers,GooglereleasedaversiontotheirMavenrepository(consideryourselvesluckyusersbecausethiswasnotavailablebeforeversion2.0).WhenusingEspresso,youneedtousethebundledTestRunneraswell.Therefore,thesetupbecomes:

dependencies{

//otherdependencies

androidTestCompile('com.android.support.test.espresso:espresso-core:2.0')

}

android{

defaultConfig{

//otherconfiguration

testInstrumentationRunner

"android.support.test.runner.AndroidJUnitRunner"

}

//AnnoyinglythereisaoverlapwithEspressodependenciesatthemoment

//addthisclosuretofixinternaljarfilenameclashes

packagingOptions{

exclude'LICENSE.txt'

}

}

OncetheEspressodependencyhasbeenaddedtoyourproject,youhaveafluidinterfacetobeabletoassertthebehavioronyourUIelements.Inourexample,wehaveanActivitythatallowsyoutoorderEspressocoffee.Whenyoupresstheorderbutton,aniceEspressoimageappears.Wewanttoverifythisbehaviorinaninstrumentationtest.

ThefirstthingtodoistosetupourActivitytotest.WeuseActivityInstrumentationTestCase2sothatwecanhaveafulllifecycleActivityrunning.YouneedtocallgetActivity()atthestartofyourtestorinthesetup()methodtoallowtheactivitytobestartedandforEspressotofindtheActivityinaresumedstate:

publicclassExampleEspressoTestextends

ActivityInstrumentationTestCase2<EspressoActivity>{

publicExampleEspressoTest(){

super(EspressoActivity.class);

}

@Override

publicvoidsetUp()throwsException{

getActivity();

}

Page 202: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Oncethesetupisdone,wecanwriteatestusingEspressotoclickourbuttonandcheckwhethertheimagewasshown(madevisible)intheActivity:

publicvoidtestClickingButtonShowsImage(){

Espresso.onView(

ViewMatchers.withId(R.id.espresso_button_order))

perform(ViewActions.click());

Espresso.onView(

ViewMatchers.withId(R.id.espresso_imageview_cup))

.check(ViewAssertions.matches(ViewMatchers.isDisplayed()));

}

ThisexampleshowstheuseofEspressotofindourorderbutton,clickonthebutton,andcheckwhetherourorderedEspressoisshowntotheuser.Espressohasafluidinterface,meaningitfollowsabuilder-stylepattern,andmostmethodcallscanbechained.Intheprecedingexample,Ishowedthefullyqualifiedclassesforclarity,butthesecaneasilybechangedtostaticimportssothatthetestisevenmorehumanreadable:

publicvoidtestClickingButtonShowsImage(){

onView(withId(R.id.espresso_button_order))

.perform(click());

onView(withId(R.id.espresso_imageview_cup))

.check(matches(isDisplayed()));

}

Thiscannowbereadinamuchmoresentencestyle.ThisexampleshowstheuseofEspressotofindourorderbuttononView(withId(R.id.espresso_button_order)).Clickonperform(click()),thenwefindthecupimageonView(withId(R.id.espresso_imageview_cup)),andcheckwhetheritisvisibletotheusercheck(matches(isDisplayed())).

Thisshowsthattheonlyclassesyouneedtothinkaboutare:

Espresso:Thisistheentrypoint.AlwaysstartwiththistointeractwithaView.ViewMatchers:ThisisusedtolocateaViewwithinthecurrenthierarchy.ViewActions:Thisisusedtoclick,longclick,andsoon,onalocatedView.ViewAssertions:ThisisusedtocheckthestateofaViewafteranactionhasbeenperformed.

EspressohasareallypowerfulAPI,whichallowsyoutotestthepositionsofviewsnexttoeachother,matchdatainaListView,getdatastraightfromaheaderorfooter,andchecktheviewsinyourActionBar/ToolBarandmanymoreassertions.Anotherfeatureisitscapabilitytodealwiththreading;EspressowillwaitforasynchronoustaskstofinishbeforeitassertswhethertheUIhaschanged.Anexplanationofthesefeaturesandmuchmoreislistedonthewikipage(https://code.google.com/p/android-test-kit/w/list).

Page 203: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 204: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryInthischapter,severalreal-worldexamplesofteststhatcoverawiderangeofcaseswerepresented.Youcanusethemasastartingpointwhilecreatingyourowntests.

Wecoveredavarietyoftestingrecipesthatyoucanextendforyourowntests.WeusedmockcontextsandshowedhowRenamingDelegatingContextcanbeusedinvarioussituationstochangethedataobtainedbythetests.Wealsoanalyzedtheinjectionofthesemockcontextsintotestdependencies.

Then,weusedActivityUnitTestCasetotestActivitiesincompleteisolation.WetestedViewsinisolationusingAndroidTestCase.WedemonstratedtheuseofMockitotomockobjectscombinedwithArgumentMatcherstoprovidecustommatchersonanyobject.Finally,wetreatedtheanalysisofpotentialmemoryleaksandtookapeekintothepoweroftestingUIwithEspresso.

Thenextchapterfocusesonmanagingyourtestenvironmenttoenableyoutoruntestsinaconsistent,fast,andalwaysdeterministicway,whichleadstoautomationandthosemischievousmonkeys!

Page 205: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 206: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter4.ManagingYourAndroidTestingEnvironmentNowthatwehaveacompleteunderstandingoftheavailableAndroidtestingSDKandhaveanicerangeoftestingrecipesreadytoassertandverifyourapp’sbehavior,itistimetoprovidedifferentconditionstorunourtests,exploreothertests,orevenusetheapplicationmanuallytounderstandwhattheenduserexperiencewouldbe.

Inthischapter,wewillcover:

CreatingAndroidVirtualDevices(AVD)toprovidedifferentconditionsandconfigurationsforanapplicationUnderstandingthedifferentconfigurationsthatwecanspecifywhilecreatingAVDsHowtorunAVDsHowtocreateheadlessemulatorsUnlockingthescreentobeabletorunallthetestsSimulatingreal-lifenetworkconditionsSpeedingupyourAVDwithHAXMAlternativestotheAndroidVirtualDeviceRunningmonkeytogenerateeventstosendtotheapplication

Page 207: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingAndroidVirtualDevicesTohavethebestchanceofdetectingproblemsrelatedtothedeviceonwhichtheapplicationisrunning,youneedthewidestpossiblecoverageofdevicefeaturesandconfigurations.

Whilefinalandconclusivetestsshouldalwaysberunonrealdevices,withtheever-increasingnumberofdevicesandformfactors,itisvirtuallyimpossiblethatyouwillhaveonedeviceofeachtotestyourapplication.Therearealsodevicefarmsinthecloudtotestonavarietyofdevices(Googleforclouddevicetesting),butsometimes,theircostisabovetheaveragedeveloperbudget.Androidprovidesawayofemulating,moreorlessverbatim,agreatvarietyoffeaturesandconfigurationjustfortheconvenienceofdifferentAVDconfigurations(anemulator).

NoteAlltheexamplesinthischapterarerunfromOSX10.9.4(Mavericks)32bitusingAndroidSDKTools23.0.5withplatform4.4.2(API20)installed.

TocreateanAVD,youcanusetheandroidavdcommandfromaterminal,orfrominsideAndroidStudio,usingTools|Android|AVDManageroritsshortcuticon.IfyouruntheAVDManagerfromaterminal,yougetaGUIthatisslightlydifferentthanwhatyougetbyrunningfromAndroidStudio,buttheybothdothesamejob.We’regoingtobeusingtheAVDManagerfromAndroidStudioasthisisthemostlikelyusecase.

Byclickingontheicon,youcanaccesstheAVDManager.Here,youpresstheCreateDevice…buttontocreateanewAVD,andthefollowingdialogboxispresented:

Now,youcanselectaprofilephoneforthehardware(let’spickNexus5),hitNext,and

Page 208: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

selectanAndroidversion(KitKatx86).HitNextagain,andyougetasummaryofyourdevice.YoucanclickonFinishandyoucreatetheAVDusingthedefaultvalues.However,ifyouneedtosupportspecificconfigurations,youcanspecifydifferenthardwareproperties.Let’schangetheAVDnametotestdevice.EvenmorepropertiesareavailablebyusingtheShowAdvancedSettingsbutton.

Awiderangeofpropertiescanbeset.Somehighlightsare:

Ramsize/SDcardsizeEmulateoruseyourwebcamasfront/backcameraChangethenetworkspeed/simulatelatency

Settingthescaleisalsoveryusefultotestyourapplicationinawindowthatresemblesthesizeofarealdevice.ItisaverycommonmistaketotestyourapplicationinanAVDwithawindowsizethatisatleasttwicethesizeofarealdevice,andusingamousepointer,believingthateverythingisfine,tolaterrealizeonaphysicaldevicewithascreenof5or6inchesthatsomeitemsontheUIareimpossibletotouchwithyourfinger.

Finally,itisalsohelpfultotestyourapplicationunderthesameconditionsrepeatedly.Tobeabletotestunderthesameconditionsagainandagain,itissometimeshelpfultodeletealltheinformationthatwasenteredintheprevioussessions.Ifthisisthecase,ensureStoreasnapshotforfasterstartupisuntickedsoastostartafresheverytime.

Page 209: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 210: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningAVDsfromthecommandlineWouldn’titbeniceifwecouldrundifferentAVDsfromthecommandlineandperhapsautomatethewaywerunorscriptourtests?

ByfreeingtheAVDfromitsUIwindow,weopenawholenewworldofautomationandscriptingpossibilities.

Well,let’sexplorethesealternatives.

Page 211: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

HeadlessemulatorAheadlessemulator(itsUIwindowisnotdisplayed)comesinveryhandywhenwerunautomatedtestsandnobodyislookingatthewindow,ortheinteractionbetweenthetestrunnerandtheapplicationissofastthatwehardlyseeanything.

Also,itisworthmentioningthat,sometimes,youcan’tunderstandwhysometestsfailuntilyouseetheinteractiononthescreen,souseyourownjudgmentwhenselectingarunningmodeforyouremulator.

OnethingthatwemayhavenoticedwhilerunningAVDsisthattheirnetworkcommunicationportsareassignedatruntime,incrementingthelastusedportby2andstartingwith5554.Thisisusedtonametheemulatorandsetitsserialnumber;forexample,theemulatorusingport5554becomesemulator-5554.ThisisveryusefulwhenwerunAVDsduringthedevelopmentprocessbecausewedon’thavetopayattentiontoportassignment.However,itcanbeveryconfusinganddifficulttotrackwhichtestrunsonwhichemulatorifwearerunningmorethanonesimultaneously.

Insuchcases,wewillbespecifyingmanualportstokeepthespecificAVDunderourcontrol.

Usually,whenwearerunningtestsonmorethanoneemulatoratthesametime,notonlydowewanttodetachthewindow,butalsoavoidsoundoutput.Wewilladdoptionsforthisaswell.

ThecommandlinetolaunchthetestAVDthatwejustcreatedisasfollows,andtheportmustbeanintegerbetween5554and5584:

$emulator-avdtestdevice-no-window-no-audio-no-boot-anim-port5580

Wecannowcheckwhetherthedeviceisinthedevicelist:

$adbdevices

Listofdevicesattached

emulator-5580device

Thenextstepistoinstalltheapplicationandthetests:

$adb-semulator-5580installYourApp.apk

347KB/s(16632bytesin0.046s):/data/local/tmp/YourApp.apk

Success

$adb-semulator-5580installYourAppTests.apk

222KB/s(16632bytesin0.072s)

pkg:/data/local/tmp/YourAppTests.apk

Success

Then,wecanusethespecifiedserialnumbertorunthetestsonit:

$adb-semulator-5580shellaminstrument-w\

com.blundell.tut.test/android.test.InstrumentationTestRunner

com.blundell.tut.test.MyTests:......

com.blundell.tut.test.MyOtherTests:..........

TestresultsforInstrumentationTestRunner=..................

Time:15.295

Page 212: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

OK(20tests)

Page 213: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

DisablingthekeyguardWecanseethetestsbeingrunwithoutthemrequiringanyinterventionandaccesstotheemulatorGUI.

Sometimes,youmightreceivesomeerrorsforteststhatarenotfailingifyouruninamorestandardapproach,likeinastandardemulatorlaunchedfromyourIDE.Insuchcases,oneofthereasonsisthattheemulatormightbelockedatthefirstscreen,andweneedtounlockittobeabletorunteststhatinvolvetheUI.

Tounlockthescreen,youcanusethefollowingcommand:

$adb-semulator-5580emueventsendEV_KEY:KEY_MENU:1EV_KEY:KEY_MENU:0

Thelockscreencanalsobedisabledprogrammatically.Intheinstrumentationtestclass,youshouldaddthefollowingcode,mostprobablyinsetup():

@Override

publicvoidsetUp()throwsException{

Activityactivity=getActivity();

Windowwindow=activity.getWindow();

window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

}

Thiswilldismissthekeyguardforthesetestsandhastheaddedadvantageofnotneedinganyextrasecuritypermissionsorchangestotheappundertest(whichthedeprecatedalternativedoes,seehttp://developer.android.com/reference/android/app/KeyguardManager.html).

Page 214: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CleaningupOncertainoccasions,youalsoneedtocleanupservicesandprocessesthatarestartedafterrunningtests.Thispreventstheresultsofthelatterfrombeinginfluencedbytheendingconditionsoftheprevioustests.Inthesecases,itisalwaysbettertostartfromaknowncondition,freeingalltheusedmemory,stoppingservices,reloadingresources,andrestartingprocesses,whichisachievablebywarm-bootingtheemulator:

$adb-semulator-5580shell'stop';sleep5;start'

Thiscommandlineopenstheemulatorshellforouremulator,andrunsthestopandstartcommands,oraspeoplesay,turningitoffandonagain.

Theoutputofthesecommandscanbemonitoredusingthelogcatcommand:

$adb-semulator-5580logcat

Youwillseemessageslikethese:

D/AndroidRuntime(1):

D/AndroidRuntime(1):>>>>>>>>>>AndroidRuntimeSTART<<<<<<<<<<

D/AndroidRuntime(1):CheckJNIisON

D/AndroidRuntime(1):---registeringnativefunctions---

I/SamplingProfilerIntegration(1):Profilerisdisabled.

I/Zygote(1):Preloadingclasses…

I/ServiceManager(2):service'connectivity''connectivity''connectivity'''

died

I/ServiceManager(2):service'throttle''throttle''throttle'''died

I/ServiceManager(2):service

'accessibility''accessibility''accessibility'''died

Page 215: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TerminatingtheemulatorOncewefinishworkingwithoneoftheheadlessemulatorinstances,westartusingthecommandmentionedearlier.Weusethefollowingcommandlinetokillit:

$adb-semulator-5580emukill

Thiswillstoptheemulatorfromfreeingtheusedresourcesandterminatingtheemulatorprocessonthehostcomputer.

Page 216: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 217: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AdditionalemulatorconfigurationsSometimes,whatweneedtotestisoutsidethereachoftheoptionsthatcanbesetwhentheAVDiscreatedorconfigured.

Oneofthecasescouldbetheneedtotestourapplicationunderdifferentlocales.Let’ssaywewanttotestourapplicationonaJapanesephone—anemulator,withthelanguageandcountrysettoJapaneseandJapanrespectively.

Wehavetheabilitytopassthesepropertiesintheemulatorcommandline.The-propcommandlineoptionallowsustosetanyofthepropertieswecouldset:

$emulator-avdtestdevice-no-window-no-audio-no-boot-anim-port5580

-proppersist.sys.language=ja-proppersist.sys.country=JP

Toverifythatoursettingsweresuccessful,wecanusethegetpropcommandtoverifythem,forexample:

$adb–semulator-5580shell"getproppersist.sys.language"

ja

$adb–semulator-5580shell"getproppersist.sys.country"

JP

Ifyouwanttoclearalltheuserdataafterplayingwiththepersistentsettings,youcanusethefollowingcommand:

$adb-semulator-5580emukill

$emulator-avdtestdevice-no-window-no-audio-no-boot-anim-port5580-

wipe-data

Afterthis,theemulatorwillstartafresh.

NoteMoreinformationandalistofavailablepropertiesforsettingtheemulatorhardwareoptionscanbefoundathttp://developer.android.com/tools/devices/managing-avds-cmdline.html#hardwareopts.

Page 218: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SimulatingnetworkconditionsItisextremelyimportanttotestunderdifferentnetworkconditions,butitisneglectedmoreoftenthannot.Thiscanleadtomisconceptionsthattheapplicationbehavesdifferentlybecauseweusethehostnetworkthatpresentsadifferentspeedandlatency.

TheAndroidemulatorsupportsnetworkthrottling,forexample,tosupportslowernetworkspeedsandhigherconnectionlatencies.ThiscanbeselectedwhenyoufirstcreateyourAVD,butcanalsobedoneintheemulatoratanytimefromthecommandlineusingthe-netspeed<speed>and-netdelay<delay>options.

Thecompletelistofsupportingoptionsisasfollows:

Fornetworkspeed:

Option Description Speeds[kbits/s]

-netspeedgsm GSM/CSD Up:14.4,down:14.4

-netspeedhscsd HSCSD Up:14.4,down:43.2

-netspeedgprs GPRS Up:40.0,down:80.0

-netspeededge EDGE/EGPRS Up:118.4,down:236.8

-netspeedumts UMTS/3G Up:128.0,down:1920.0

-netspeedhsdpa HSDPA Up:348.0,down:14400.0

-netspeedfull Nolimit Up:0.0,down:0.0

-netspeed<num> Selectboththeuploadanddownloadspeed Up:asspecified,down:asspecified

-netspeed<up>:<down> Selecttheindividualupanddownspeed Up:asspecified,down:asspecified

Forlatency:

Option Description Delay[msec]

-netdelaygprs GPRS Min150,max550

-netdelayedge EDGE/EGPRS Min80,max400

-netdelayumts UMTS/3G Min35,max200

-netdelaynone Nolatency Min0,max0

-netdelay<num> Selectexactlatency Latencyasspecified

-netdelay<min>:<max> Selectminandmaxlatencies Minimumandmaximumlatenciesasspecified

Ifthevaluesarenotspecified,theemulatorusesthefollowingdefaultvalues:

Page 219: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ThedefaultnetworkspeedisfullThedefaultnetworklatencyisnone

ThisisanexampleofanemulatorusingtheseoptionstoselecttheGSMnetworkspeedof14.4kbits/secandaGPRSlatencyof150to500msecs:

$emulator-avdtestdevice-port5580-netspeedgsm-netdelaygprs

Oncetheemulatorisrunning,youcanverifythesenetworksettingsorchangetheminteractivelyusingtheAndroidconsoleinsideaTelnetclient:

$telnetlocalhost5580

Trying127.0.0.1…

Connectedtolocalhost.

Escapecharacteris'^]'.

AndroidConsole:type'help'foralistofcommands

OK

Afterweareconnected,wecantypethefollowingcommand:

networkstatus

Currentnetworkstatus:

downloadspeed:14400bits/s(1.8KB/s)

uploadspeed:14400bits/s(1.8KB/s)

minimumlatency:150ms

maximumlatency:550ms

OK

Youcanusetheemulatortotestapplicationsusingnetworkserviceseithermanuallyorinanautomatedway.

Insomecases,thisnotonlyinvolvesthrottlingthenetworkspeedbutalsochangingthestateoftheGPRSconnectiontoinvestigatehowtheapplicationbehavesandcopeswiththesesituations.Tochangethisstatus,wecanalsousetheAndroidconsoleinarunningemulator.

Forexample,tounregistertheemulatorfromthenetwork,wecanuse:

$telnetlocalhost5580

AfterreceivingtheOKsubprompt,wecansetthedatanetworkmodeasunregisteredbyissuingthefollowingcommand.Thiswillturnoffalldata:

gsmdataunregistered

OK

quit

Connectionclosedbyforeignhost.

Aftertestingtheapplicationunderthiscondition,youcanconnectitagainbyusingthefollowingcommandline:

gsmdatahome

OK

Toverifythestatus,youcanusethefollowingcommandlines:

Page 220: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

gsmstatus

gsmvoicestate:home

gsmdatastate:home

OK

Page 221: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 222: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SpeedingupyourAVDwithHAXMWhenusingAndroidVirtualDevices,you’llnoticethattheyaren’tthemostresponsiveofemulators.ThisisduetothefactthattheAVDemulatordoesnotsupporthardwareGL,andsotheGLcodegetstranslatedintoARMsoftware,whichgetsrunonhardwareemulatedbyQEMU(QEMUisthehostedvirtualmachinemonitorthatAVDsrunontopof).Googlehasbeenworkingonthisproblem,andnow,efficientuseofthehostGPUisboostingspeed(SDK17).Responsivenesshasimprovedonthisandabovelevelsofemulator.

AnotherspeedboostcanbegainedbyusingIntel’sHardwareAcceleratedExecutionManager(HAXM).Youcangeta5to10timesspeedboostonyourAVDsthatrunx86asitwillexecutetheCPUcommandsnatively.

HAXMworksbyallowingtheCPUcommandstoberunonyourhardware(thatisyourIntelCPU),whereasearlier,QEMUwouldbesimulatingtheCPU,andallcommandswouldbethroughsoftware,whichiswhytheoriginalarchitectureiscumbersome.

Aspertherequirements,youneedtohaveanIntel-basedprocessorwithVT(VirtualizationTechnology)supportandanx86-basedemulatorwithminimumSDK10(Gingerbread).IntelclaimsthatmostIntelprocessorsfrom2005onwardswillsupportVToffloadingasstandard.

Installationisstraightforward;downloadHAXMfromtheextrassectionoftheAndroidSDKManager,locatethedownloadedfile,andfollowtheinstallerinstructions.Youcanclarifyasuccessfulinstallationbyrunningthiscommandfromaterminal:

kextstat|grepintel

Ifyougetamessagethatcontainscom.intel.kext.intelhaxm,you’veinstalledandcannowrunyourspeedyx86emulator.Thereisnothingelseyouhavetodo,justensuretheCPU/ABIofyourAndroidemulatorisx86andHAXMwillberunninginthebackgroundforyou.

Page 223: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 224: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AlternativestotheAVDTheAndroidVirtualDeviceisnotyouronlywayofrunningAndroidapps.Therearenowafewsolutionsyoucanchoosefrom.AquicksearchonGooglecanbringupthislist(Iwon’twriteithereastheycanquicklygetoutofdate).OneofthesethatIpersonallyrecommendistheGenyMotionemulator.ThisisanAndroidemulatorthatusesx86architecturevirtualizationtomakeitmuchmoreefficient.ItrunsmuchfasterandsmootherthantheAVD.Thedownsidebeingitisonlyfreeforpersonaluse,andasofthiswriting,itdoesnotemulateallthesensorsofadevice,butIknowtheyarebusyworkingonthis.

Page 225: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 226: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningmonkeyYoumightknowabouttheinfinitemonkeytheorem.Thistheoremstatesthatamonkeythathitskeysatrandomonatypewriterkeyboardforaninfiniteamountoftimewilleventuallytypeagiventext,suchasthecompleteworksofWilliamShakespeare.TheAndroidversionofthistheoremstatesthatamonkeythatproducesrandomtouchesonadevicecouldcrashyourapplicationin,well,muchlessthananinfiniteamountoftime.

Withthis,Androidfeaturesamonkeyapplication(http://goo.gl/LSWg85)thatwillgeneratetherandomeventsinsteadofarealmonkey.

Thesimplestwaytorunmonkeyagainstourapplicationtogeneraterandomeventsis:

$adb-eshellmonkey-pcom.blundell.tut-v-v1000

Youwillbereceivingthisoutput:

Eventsinjected:1000

:Sendingrotationdegree=0,persist=false

:Dropped:keys=0pointers=4trackballs=0flips=0rotations=0

##Networkstats:elapsedtime=2577ms(0msmobile,0mswifi,2577msnot

connected)

//Monkeyfinished

Themonkeywillsendeventsonlytothespecifiedpackage(-p),inthiscasecom.blundell.tut,inaveryverbosemanner(-v-v).Thecountofeventssentwillbe1000.

Page 227: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Theclient-servermonkeyThereisanotherwayofrunningmonkey.Italsopresentsaclient-servermodelthatultimatelyallowsforthecreationofscriptsthatcontrolwhateventsaresentanddoesnotrelyonlyonrandomgeneration.

Usually,theportusedbymonkeyis1080,butyoucanuseanotheroneifitbettersuitsyourpreferences:

$adb-eshellmonkey-pcom.blundell.tut--port1080&

Then,weneedtoredirecttheemulatorport:

$adb-eforwardtcp:1080tcp:1080

Now,wearereadytosendevents.Todoitmanually,wecanuseaTelnetclient:

$telnetlocalhost1080

Aftertheconnectionisestablished,wecantypethespecificmonkeycommand:

tap150200

OK

Tofinish,exitthetelnetcommand.

Ifweneedtoexercisetheapplicationrepeatedly,itismuchmoreconvenienttocreateascriptwiththecommandswewanttosend.Amonkeyscriptcouldlooklikethis:

#monkey

tap200200

typeHelloWorld

tap200350

tap200200

pressDEL

pressDEL

pressDEL

pressDEL

pressDEL

typeMonkey

tap200350

NoteTheAPIformonkeytapistap<xpixelposition><ypixelposition>.

Therefore,ifyouarenotrunninganemulatorwiththesame§resolutionastheoneyourmonkeycommandwasrecordedwith,youcouldgetincorrecttoucheventsfromyourmonkey.

Afterhavingstartedtheexampleapplicationforthischapter,wecanrunthisscripttoexercisetheuserinterface.Tostarttheapplication,youcanusetheemulatorwindowandclickonitslaunchericonorusethecommandlinethatstatestheactivityyouwanttostart,whichistheonlyalternativeiftheemulatorisheadless,asfollows:

$adbshellamstart-ncom.blundell.tut/.MonkeyActivity

Page 228: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thisisinformedinthelogbythisline:

Starting:Intent{cmp=com.blundell.tut/.MonkeyActivity}

Oncetheapplicationhasstarted,youcansendtheeventsusingthescriptandthenetcatutility:

$nclocalhost1080<ch_4_code_ex_10.txt

Thiswillsendtheeventscontainedinthescriptfiletotheemulator.Thesearethefollowingevents:

1. Touchandselecttheedittextinput.2. TypeHelloWorld.3. Tapthebuttontoshowthetoast.4. Touchandselecttheedittextagain.5. Deleteitscontent.6. TypeMonkey.7. TapthebuttontoshowthetoastHelloMonkey.

Inthismanner,simplescriptsthatconsistoftoucheventsandkeypressescanbecreated.

Page 229: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 230: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestscriptingwithmonkeyrunnerThepossibilitiesofmonkeyarefairlylimited,andthelackofflowcontrolrestrictsitsusetoverysimplecases.Tocircumventtheselimitations,anewprojectwascreated,whichwasnamedmonkeyrunner.Notwithstandingthis,thenameisalmostthesameandleadstoahugeamountofconfusionbecausetheyarenotrelatedinanyway.

Monkeyrunner,whichisalreadyincludedinthelatestversionsoftheAndroidSDK,isatoolthatprovidesanAPIforthepurposeofwritingscriptsthatexternallycontrolanAndroiddeviceoremulator.

MonkeyrunnerisbuiltontopofJython(http://jython.org/),aversionofthePythonprogramminglanguage(http://python.org/),whichisdesignedtorunontheJavaplatform.

Accordingtoitsdocumentation,themonkeyrunnertoolprovidestheseuniquefeaturesforAndroidtesting.Thesearejustthehighlightsofthecompletelistoffeatures,examples,andreferencedocumentationthatcanbeobtainedfromthemonkeyrunnerhomepage(http://developer.android.com/tools/help/monkeyrunner_concepts.html):

Multipledevicecontrol:ThemonkeyrunnerAPIcanapplyoneormoretestsuitesacrossmultipledevicesoremulators.Youcanphysicallyattachallthedevicesorstartupalltheemulators(orboth)atonce,connecttoeachoneinturnprogrammatically,andthenrunoneormoretests.Youcanalsostartupanemulatorconfigurationprogrammatically,runoneormoretests,andthenshutdowntheemulator.Functionaltesting:monkeyrunnercanrunanautomatedstart-to-finishtestofanAndroidapplication.Youprovideinputvalueswithkeystrokesortouchevents,andviewtheresultsasscreenshots.Regressiontesting:monkeyrunnercantesttheapplicationstabilitybyrunninganapplicationandcomparingitsoutputscreenshotstoasetofscreenshotsthatareknowntobecorrect.Extensibleautomation:SincemonkeyrunnerisanAPItoolkit,youcandevelopanentiresystemofPython-basedmodulesandprogramstocontrolAndroiddevices.BesidesusingthemonkeyrunnerAPIitself,youcanusethestandardPythonOSandsubprocessmodulestocallAndroidtoolssuchasAndroidDebugBridge.YoucanalsoaddyourownclassestothemonkeyrunnerAPI.ThisisdescribedinmoredetailintheonlinedocumentationunderExtendingmonkeyrunnerwithplugins.

Page 231: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GettingtestscreenshotsCurrently,oneofthemostevidentusesofmonkeyrunnerisgettingscreenshotsoftheapplicationundertesttobefurtheranalyzedorcompared.

Thesescreenshotscanbeobtainedwiththehelpofthefollowingsteps:

1. Importtherequiredmodules.2. Createtheconnectionwiththedevice.3. Checkwhetherthedeviceisconnected.4. Starttheactivity.5. Addsomedelayfortheactivitystartup.6. Type‘hello’.7. Addsomedelaytoallowfortheeventstobeprocessed.8. Obtainthescreenshots.9. Saveittoafile.10. PressBACKtoexittheActivity.

Thefollowingisthecodeforthescriptneededtoperformtheprecedingsteps:

#!/usr/bin/envmonkeyrunner

importsys

#Importsthemonkeyrunnermodulesusedbythisprogram

fromcom.android.monkeyrunnerimportMonkeyRunner,MonkeyDevice,

MonkeyImage

#Connectstothecurrentdevice,returningaMonkeyDeviceobject

device=MonkeyRunner.waitForConnection()

ifnotdevice:

print>>sys.stderr,"Couldn't""getconnection"

sys.exit(1)

device.startActivity(component='com'.blundell.tut/.MonkeyActivity')

MonkeyRunner.sleep(3.0)

device.type("hello")

#Takesascreenshot

MonkeyRunner.sleep(3.0)

result=device.takeSnapshot()

#Writesthescreenshottoafile

result.writeToFile('/tmp/device.png')

device.press('KEYCODE_BACK','DOWN'_AND_UP')

Oncethisscriptruns,youwillfindthescreenshotoftheactivityin/tmp/device.png.

Page 232: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RecordandplaybackIfyouneedsomethingsimpler,thereisnoneedtomanuallycreatethesescripts.Tosimplifytheprocess,themonkey_recorder.pyscript,whichisincludedintheAndroidsourcerepositoryintheSDKproject(http://goo.gl/6Qv0z0),canbeusedtorecordeventdescriptionsthatarelaterinterpretedbyanotherscriptcalledmonkey_playback.py.

Runmonkey_recorder.pyfromthecommandline,andyouwillbepresentedwiththisUI:

Thisinterfacehasatoolbarwithbuttonstoinsertdifferentcommandsintherecordedscript:

Button Description

WaitThisdenoteshowmanysecondstowait.

Thisnumberisrequestedbyadialogbox.

PressaButton ThissendstheMENU,HOME,RECENTS,andSEARCHbuttons.PresstheDownorUpevent.

TypeSomething Thissendsastring.

Fling Thissendsaflingeventinthespecifieddirection,distance,andnumberofsteps.

Page 233: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ExportActions Thissavesthescript.

RefreshDisplay Thisrefreshesthecopyofthescreenshotthatisdisplayed.

Oncethescriptiscompleted,saveit,let’ssayasscript.mr,andthen,youcanre-runitbyusingthiscommandline:

$monkey_playback.pyscript.mr

Now,alltheeventswillbereplayed.

Page 234: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 235: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryInthischapter,wecoveredallthealternativeswehadtoexposeourapplicationanditsteststoawiderangeofconditionsandconfigurations,rangingfromdifferentscreensizes,theavailabilityofdevicessuchascamerasorkeyboards,tosimulatingreal-lifenetworkconditionstodetectproblemsinourapplication.

Wealsoanalyzedalloftheoptionswehaveinordertobeabletocontrolemulatorsremotelywhentheyaredetachedfromitswindow.Thispreparesthefoundationofdoingtestfirstdevelopment,andwewillcomebacktothistopicinChapter6,PracticingTest-drivenDevelopment.

WediscussedthespeedoftheAVDandsawhowwecanimprovethis,aswellaslookedatemulatorchoicesinGenyMotionandHAXM.Finally,somescriptingalternativeswereintroduced,andexamplestogetyoustartedwereprovided.

Inthenextchapter,wewilldiscovercontinuousintegration—awayofworkingthatreliesontheabilitytoautomaticallyrunallthetestsuitesandconfigure,start,andstopemulatorsinordertoautomatethecompletebuildprocess.

Page 236: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 237: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter5.DiscoveringContinuousIntegrationContinuousintegrationisoneagiletechniqueforsoftwareengineeringthataimstoimprovesoftwarequalityandreducethetimetakentointegratechangesbycontinuouslyapplyingintegrationandtestingfrequently,asopposedtothemoretraditionalapproachofintegratingandtestingattheendofthedevelopmentcycle.

Continuousintegrationhasreceivedabroadadoption,andaproliferationofcommercialtoolsandopensourceprojectsisacleardemonstrationofitssuccess.Thatisnotverydifficulttounderstand,asanybodywhoduringtheirprofessionalcareerhasparticipatedinasoftwaredevelopmentprojectusingatraditionalapproachisverylikelytohaveexperiencedtheso-calledintegrationhell,wherethetimeittakestointegratethechangesexceedsthetimeittooktomakethechanges.Doesthisremindyouofanything?Onthecontrary,continuousintegrationisthepracticeofintegratingchangesfrequentlyandinsmallsteps.Thesestepsarenegligibleand,ifanerrorisnoticed,itissosmallthatitcanbefixedimmediately.Themostcommonpracticeistotriggerthebuildprocessaftereverycommittothesourcecoderepository.

Thispracticealsoimpliesotherrequirements,besidethesourcecodebeingmaintainedbyaversioncontrolsystem(VCS):

Buildsshouldbeautomatedbyrunningasinglecommand.Thisfeaturehasbeensupportedforaverylongtimebytoolssuchasmakeandant,andmorerecentlybymavenandgradle.Buildsshouldbeself-testingtoconfirmthatthenewlybuiltsoftwaremeetstheexpectationsofthedevelopers.Buildartifactsandresultsofthetestsshouldbeeasytofindandview.

WhenwewritetestsforourAndroidprojects,wewouldliketotakeadvantageofcontinuousintegration.Toachievethis,wewanttocreateamodelthatcoexistswiththetraditionalIDEenvironmentandAndroidbuildtools,sowecanrunandinstallourappnomattertheenvironmentsuchasCIbox,IDEormanually.

Inthischapter,wearegoingtodiscuss:

AutomatingthebuildprocessIntroducingversioncontrolsystemstotheprocessContinuousintegrationwithJenkinsAutomatingtests

Afterthischapter,youwillbeabletoapplycontinuousintegrationtoyourownprojectnomatteritssize,whetheritisamediumorlargesoftwareprojectemployingdozensofdevelopersoritisjustyouprogrammingsolo.

NoteTheoriginalarticleoncontinuousintegrationwaswrittenbyMartinFowlerbackin2000

Page 238: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

(http://www.martinfowler.com/articles/continuousIntegration.html),anddescribestheexperienceofputtingtogethercontinuousintegrationonalargesoftwareproject.

Page 239: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

BuildingAndroidapplicationsmanuallyusingGradleIfweaimtoincorporatecontinuousintegrationintoourdevelopmentprocess,thefirststepwillbetobuildAndroidapplicationsmanually,aswecancombineanintegrationmachinewiththemanualbuildingtechniquetoautomatetheprocedure.

Indoingthis,weintendtokeepourprojectcompatiblewiththeIDEandcommand-linebuildingprocess,andthisiswhatwearegoingtodo.Automatedbuildingisagreatadvantageandspeedsupthedevelopmentprocessbybuildingandeventuallyshowingtheerrorsthatmayexistinyourprojectimmediately.Wheneditingresourcesorotherfilesthatgenerateintermediateclasses,aCIisaninvaluabletool;otherwise,somesimpleerrorswouldbediscoveredtoolateinthebuildingprocess.Followingthemantraoffailoften,failfastisarecommendedpractice.

Fortunately,AndroidsupportsmanualbuildingwiththeexistingtoolsandnotmucheffortisneededtomergemanualIDEbuildsandautomaticCIbuildsinthesameproject.Insuchcases,buildingmanuallyinsideyourIDEwithGradleissupported.However,otheroptionssuchasAntexisttoothatarenolongersupportedbydefault,andMavenorMakethatarenotsupportedoutofthebox.

NoteGradleisbuildautomationevolved.GradlecombinesthepowerandflexibilityofAntwiththedependencymanagementandconventionsofMavenintoamoreeffectivewaytobuild.

Moreinformationcanbefoundatitshomepage,http://gradle.org/.

Atthetimeofwriting,projectsbasedonAndroidGradlerequireatleastGradle2.2ornewerversions.

ItisworthnotingherethattheentireAndroidopensourceprojectisnotbuiltbyGradlebutbuiltbyanincrediblycomplexstructureofmakefiles,andthismethodisusedeventobuildtheapplicationsthatareincludedbytheplatformsuchasCalculator,Contacts,Settings,andsoon.

WhencreatinganewprojectwithAndroidStudio,thetemplateprojectwillalreadybebeingbuiltwithGradle.Thismeansyoucanalreadybuildtheprojectmanuallyfromthecommandline.Executing./gradlewtasksfromthebaseofyourprojectwillgiveyouafulllistoftasksthatcanberun.Themostcommonlyusedtasksareasshowninthefollowingtable:

Target Description

build Assemblesandteststhisproject

clean Deletesthebuilddirectory

Page 240: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

tasksDisplaysthetasksrunnablefromrootprojectx(someofthedisplayedtasksmaybelongtosubprojects)

installDebug InstallstheDebugbuild

installDebugTest InstallstheTestbuildfortheDebugbuild

connectedAndroidTest InstallsandrunsthetestsforBuilddebugonconnecteddevices

uninstallDebug UninstallstheDebugbuild

Thecommandsprefixedwith./gradlewuseaninstallationofGradlethatisactuallyshippedinsideyourprojectsourcecode.Thisisknownasthegradlewrapper.Therefore,youdonotneedGradleinstalledonyourlocalmachine!However,ifyoudohaveGradleinstalledlocally,allcommandsusingthewrappercanbereplacedwith./gradle.Ifthereareseveraldevicesoremulatorsconnectedtothebuildmachine,thesecommandswillrun/installonthemall.ThisisgreatforourCIsetup,meaningwecanrunourtestsonalltheprovideddevicessothatwecanhandleanumberofconfigurationsandAndroidversions.Ifyoudowanttoinstallonjustoneforsomeotherreason,thisispossiblethroughtheDeviceProvidersAPIbutisoutofthescopeofthisbook.Iencourageyoutoreadmoreathttp://tools.android.comandalsocheckoutthewiderangeofGradlepluginsavailabletohelpyouwiththis.

Nowwecanrunthiscommandtoinstallourapplication:

$./gradlewinstallDebug

Thisisthestartandendoftheoutputgenerated:

Configuring>3/3projects

:app:assembleDebug

:app:installDebug

InstallingAPK'app'-debug.'apk'on'emulator-5554'InstallingAPK'app'-

debug.'apk'on'Samsung'Galaxy'S4'

Installedon2devices.

BUILDSUCCESSFUL

Totaltime:11.011secs

Runningtheprecedingcommandmentioned,thefollowingstepsareexecuted:

Compilationofthesources,includingresource,AIDL,andJavafilesConversionofthecompiledfilesintothenativeAndroidformatPackagecreationandsigningInstallationontothegivendeviceoremulator

OncewehavetheAPKinstalled,andbecausewearenowdoingeverythingfromthecommandline,wecanevenstartanActivitysuchasEspressoActivity.UsingtheamstartcommandandanIntentusingtheMAINactionandtheActivityweareinterestedtolaunchasthecomponent,wecancreateacommandlineasfollows:

adb-semulator-5554shellamstart-aandroid.intent.action.MAIN-n

Page 241: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

com.blundell.tut/.EspressoActivity

TheActivityisstartedasyoucanverifyintheemulator.Nowthenextthingtodowouldbetoinstallthetestprojectforourapplication,andthenusethecommandlinetorunthesetests(asdiscussedinpreviouschapters).Finally,whentheyarecompleted,weshoulduninstalltheapplication.Ifyoureadthecommandlistcarefully,youmayhavenoticedthatluckilythishasbeendoneforuswiththeconnectedAndroidTestGradletask.

Afterrunningthecommand,wewillobtainthetestsresults.Iftheypass,theoutputissimplyasfollows:

:app:connectedAndroidTest

BUILDSUCCESSFUL

Totaltime:9.812secs

Howeveriftheyfail,theoutputismoredetailedandalinktothefilewhereyoucanseethefullstacktraceandthereasonswhyeachtestfailedispresented:

:app:connectedAndroidTest

com.blundell.tut.ExampleEspressoTest>

testClickingButtonShowsImage[emulator-5554]FAILED

android.view.ViewRootImpl$CalledFromWrongThreadException:Onlytheoriginal

threadthatcreatedaviewhierarchycantouchitsviews.

atandroid.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024)

FAILURE:Buildfailedwithanexception.

*Whatwentwrong:

Executionfailedfortask':app:connectedAndroidTest.

>Therewerefailingtests.Seethereportat:

file:///AndroidApplicationTestingGuide/app/build/outputs/reports/androidTes

ts/connected/index.html

BUILDFAILED

Totaltime:15.532secs.

Wehavedoneeverythingfromthecommandlinebyjustinvokingsomesimplecommands,whichiswhatwewerelookingforinordertofeedthisintoacontinuousintegrationprocess.

Page 242: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 243: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Git–thefastversioncontrolsystemGitisafreeandopensource,distributedversioncontrolsystemdesignedtohandleeverythingfromsmalltoverylargeprojectswithspeedandefficiency.ItisverysimpletosetupsoIstronglyrecommenditsuseevenforpersonalprojects.Thereisnoprojectsimpleenoughthatcouldnotbenefitfromtheapplicationofthistool.Youcanfindinformationanddownloadsathttp://git-scm.com/.

AversioncontrolsystemorVCS(alsoknownassourcecodemanagementorSCM)isanunavoidableelementfordevelopmentprojectswheremorethanonedeveloperisinvolvedandthebestpracticeevenifcodingsolo.Furthermore,eventhoughitispossibletoapplycontinuousintegrationwithnoVCSinplace(asaVCSisnotarequisiteofCI),itisnotareasonableorrecommendedpracticetoavoidit.

Otherandprobablymoretraditional(seelegacy),optionsexistintheVCSarenasuchasSubversionorCVS,whichyouarefreetouseifyoufeelmorecomfortable.Otherwise,GitisusedextensivelybytheAndroidprojecttohostGoogle’sowncodeandexamplessoitisworthinvestingsometimetoatleastunderstandthebasics.

Havingsaidthatandrememberingthatthisisaverybroadsubjecttojustifyabookinitself(andcertainlytherearesomegoodbooksaboutit),wearediscussingherethemostbasictopicsandsupplyingexamplestogetyoustartedifyouhaven’tembracedthispracticeyet.

Page 244: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingalocalGitrepositoryThesearethesimplestpossiblecommandstocreatealocalrepositoryandpopulateitwiththeinitialsourcecodeforourprojects.InthiscaseweareagainusingtheAndroidApplicationTestingGuideprojectcreatedandusedinpreviouschapters.Wecopythecodeweusedintheprevioussection,wherewebuiltmanually:

$mkdirAndroidApplicationTestingGuide

$cdAndroidApplicationTestingGuide

$gitinit

$cp-a<path/to/original>/AndroidApplicationTestingGuide/

$gradlewclean

$rmlocal.properties

$gitadd.

$gitcommit-m"Initialcommit"

Wecreatethenewprojectdirectory,initializetheGitrepository,copytheinitialcontent,cleananddeleteourpreviousautogeneratedfiles,removethelocal.propertiesfile,addeverythingtotherepository,andcommit.

TipThelocal.propertiesfilemustneverbecheckedinaversioncontrolsystemasitcontainsinformationspecifictoyourlocalconfiguration.Youmightalsowanttolookatcreatinga.gitignorefile.Thisfileallowsyoutodefinewhatfilesarenotcheckedin(suchasauto-generatedfiles).Anexampleofthe.gitignorefilecanbefoundathttps://github.com/github/gitignore.

Atthispoint,wehaveourprojectrepositorycontainingtheinitialsourcecodeforourapplicationandallofitstests.Wehaven’talteredthestructuresotheprojectisstillcompatiblewithourIDEandGradleforwhenwecontinuedeveloping,locallybuilding,andcontinuouslyintegrating.

Thenextstepistohaveourprojectbuiltandtestedautomaticallyeverytimewecommitachangetothesourcecode.

Page 245: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 246: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ContinuousintegrationwithJenkinsJenkinsisanopensource,extensiblecontinuousintegrationserverthathastheabilitytobuildandtestsoftwareprojectsormonitortheexecutionofexternaljobs.Jenkinsiseasytoinstallandconfigure,andisthuswidelyused.Thatmakesitidealasanexampletolearncontinuousintegration.

Page 247: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

InstallingandconfiguringJenkinsWementionedeasyinstallationasoneoftheadvantagesofJenkinsandinstallationcouldnotbeanyeasier.Downloadthenativepackagefortheoperatingsystemofyourchoicefromhttp://jenkins-ci.org/.Therearenativepackagesforallmajorserveranddesktopoperatingsystems.Inthefollowingexamples,wewillbeusingversion1.592.Wewillrunthe.warfileafterdownloadingit,sinceitdoesnotrequireadministrativeprivilegestodoso.

Oncefinished,copythewarintoaselecteddirectory,~/jenkins,andthenrunthefollowingcommand:

$java-jar~/jenkins/jenkins-1.592.war

ThisexpandsandstartsJenkins.

Thedefaultconfigurationusesport8080astheHTTPlistenerport,sopointingyourbrowserofchoicetohttp://localhost:8080shouldpresentyouwiththeJenkinshomepage.YoucanverifyandchangeJenkins’operatingparameterifrequired,byaccessingtheManageJenkinsscreen.WeshouldaddtothisconfigurationthepluginsneededforGitintegration,buildingwithGradle,checkingtestresults,andsupportforAndroidemulatorduringbuilds.ThesepluginsarenamedGitplugin,Gradleplugin,JUnitplugin,andAndroidEmulatorplugin,respectively.

ThisfollowingscreenshotdisplaystheinformationyoucanobtainaboutthepluginsfollowingthelinkavailableontheJenkinspluginadministrationpage:

Page 248: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AfterinstallingandrestartingJenkins,thesepluginswillbeavailableforuse.Ournextstepistocreatethejobsnecessarytobuildtheprojects.

Page 249: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingthejobsLet’sstartbycreatingtheAndroidApplicationTestingGuidejobusingNewItemontheJenkinshomepage.Nameitaftertheproject.Differentkindsofjobscanbecreated;inthiscase,weselectFreestyleproject,allowingyoutoconnectanySCMwithanybuildsystem.

AfterclickingontheOKbutton,youwillbepresentedwiththespecificjoboptions,whicharedescribedinthefollowingtable.Thisisatthetopofthejobproperties’pageasfollows:

AlloftheoptionsintheNewItemscreenhaveahelptextassociated,sohereweareonlyexplainingtheonesweenter:

Option Description

Projectname Thenamegiventotheproject.

Description Optionaldescription.

DiscardOldBuilds Thishelpsyousaveondiskconsumptionbymanaginghowlongtokeeprecordsofthebuilds(suchasconsoleoutput,buildartifacts,andsoon).

ThisbuildisparameterizedThisallowsyoutoconfigureparametersthatarepassedtothebuildprocesstocreateparameterizedbuilds,forinstance,using$ANDROID_HOMEinsteadofhardcodingapath.

SourceCodeManagement

AlsoknownasVCS,whereisthesourcecodefortheproject?Inthiscase,weuseGitandarepositorywheretheURListheabsolutepathoftherepositorywecreatedearlier.Forexample,/git-repo/AndroidApplicationTestingGuide.

Howthisprojectisautomaticallybuilt.Inthiscase,wewanteverychangeinthesourcecodetotriggertheautomaticbuild,soweselectPollSCM.

TheotheroptionistouseBuildperiodically.Thisfeatureisprimarilyto

Page 250: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

BuildTriggers

useJenkinsasacronreplacement,anditisnotidealtocontinuouslybuildsoftwareprojects.Whenpeoplefirststartcontinuousintegration,theyareoftensousedtotheideaofregularlyscheduledbuildssuchasnightly/weeklythattheyusethisfeature.However,thepointofcontinuousintegrationistostartabuildassoonasachangeismade,toprovideaquickfeedbacktothechange.

Thisoptioncanbeusedforlongerrunningbuildsliketestsuitesthatperhapstestperformancewhenthebuildrunsfor1hourforexample(configureittorunatmidnight).Italsocanbeusedtoreleasenewversions,nightly,orweekly.

Schedule

ThisfieldfollowsthesyntaxofCron(withminordifferences).Specifically,eachlineconsistsoffivefieldsseparatedbyTABorwhitespace:

MINUTEHOURDOMMONTHDOW.

Forexample,ifwewanttopollcontinuouslyat30minutespastthehour,specify:30****

Checkthedocumentationforacompleteexplanationofalltheoptions.

Buildenvironment ThisoptionletsyouspecifydifferentoptionsforthebuildenvironmentandfortheAndroidemulatorthatmayrunduringthebuild.

Build

Thisoptiondescribesthebuildsteps.WeselectInvokeGradlescriptaswereproducethestepswedidbeforetomanuallybuildandtesttheproject.

WewillselectUseGradleWrappersothatourprojectdoesn’trelyontheCIboxesbuiltintheGradleversion.

Then,intheTasksbox,wewanttowritecleanconnectedAndroidTest.

Postbuildactions

Theseareaseriesofactionswecandoafterthebuildisdone.WeareinterestedinsavingtheAPKssoweenableArchivetheartifactsandthendefinethepathforthemasFilestoarchive;inthisprecisecase,itis**/*-debug.apk.

Save Savesthechangeswejustmadeandcompletesthebuildjobcreation.

NowthatourCIbuildissetup,therearefollowingtwooptions:

YoucanforceabuildusingBuildNowOrintroducesomechangestothesourcecode,pushwithGit,andwaitforthemtobedetectedbyourpollingstrategy

Eitherway,wewillgetourprojectbuiltandourartifactsreadytobeusedforotherpurposes,suchasdependencyprojectsorQA.Unfortunately,ifyoudidruntheCIbuild,itwouldfailspectacularlyastherearenodevicesattached.Yourchoicesare,attacharealdeviceorusetheAndroidEmulatorpluginthatwejustinstalled.Let’susetheplugin.FromJenkins,gotothejobwejustcreatedandclickonConfigure.

Option Description

Ourintentionistoinstallandrunthetestsonanemulator.Soforourbuildenvironment,weusethefacilitiesprovidedbytheAndroidEmulatorPlugin.ThiscomesinhandyifyouwishtoautomaticallystartanAndroidemulatorofyourchoicebeforethebuildstepsexecute,withtheemulatorbeingstopped

Page 251: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Buildenvironment

afterthebuildingiscomplete.

Youcanchoosetostartapredefined,existingAndroidemulatorinstance(AVD).

Alternatively,theplugincanautomaticallycreateanewemulatoronthebuildslavewithpropertiesyouspecifyhere.

Inanycase,thelogcatoutputwillautomaticallybecapturedandarchived.

SelectRunemulatorwithproperties.

Then,select4.4fortheAndroidOSversion,320DPIfortheScreendensityandWQVGAforScreenresolution.

Feelfreetoexperimentandselecttheoptionsthatbettersuityourneeds.

Commonemulatoroptions

WewouldliketoResetemulatorstateatstart-uptowipeuserdataanddisableShowemulatorwindow,sotheemulatorwindowisnotdisplayed.

Afterconfiguringandbuildingthisproject,wehavetheAPKinstalledonthetargetemulatorandthetestsarerunning.

Page 252: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ObtainingAndroidtestresultsOncethetestsarerun,theresultsaresavedasXMLfilesinsidetheproject’sbuildfolderat/AndroidApplicationTestingGuides/app/build/outputs/androidTest-results/connected/.

Theyarenogoodtousthere.ItwouldbeniceifwecouldreadtheresultsofourtestsinJenkinsandhavethemdisplayedinaniceHTMLformat;anotherJenkinsplugintotherescue.JUnitPluginenablesapostbuildactionthatasksyouwhereyourJUnitreportsarestoredandwillthenretrievethemforeasyviewingintheprojectscreenofJenkinsastestresults.Inthisscenario,weusethePost-buildActionsalsointhejobconfiguration’spage.

Havingdoneallofthestepspreviouslydescribed,onlyforcingabuildislefttoseetheresults.Option

Description

PublishJUnittestresultreport

Whenthisoptionisconfigured,theJUnitpluginonJenkinscanprovideusefulinformationabouttestresults,suchashistoricaltestresulttrends,awebUItoviewtestreports,trackingfailures,andsoon.

ItrequiresaregextolookuptheJUnitresultfiles.Iwouldrecommend**/TEST*.xml.ThisregexshouldmatchallJUnittestresults,includingthoseoftheAndroidconnectedtests;praiseinresearchheregoestoAdamBrown.Ifyouchangetheregex,besurenottoincludeanynon-reportfilesintothispattern.

Onceafewbuildshaverunwithtestresults,youshouldstartseeingsometrendchartsdisplayingtheevolutionoftests.

ClickonBuildNowandafterafewmoments,youwillseeyourtestresultsandstatisticsdisplayedinasimilarwayasthefollowingscreenshotdepicts:

Fromhere,wecaneasilyunderstandourprojectstatus.ClickingonLatestTestResultshowsyouhowmanytestsfailedandwhy.YoucansearchthroughthefailedtestsandcanalsofindtheextensiveErrormessageandStacktraceoptions.

Itisalsoreallyhelpfultounderstandtheevolutionofaprojectthroughtheevaluationof

Page 253: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

differenttrendsandJenkinsisabletoprovidesuchinformation.Everyprojectpresentsthecurrenttrendsusingweather-likeiconsfromsunny,whenthehealthoftheprojectincreasesby80percent,andtothunderstormwhenthehealthliesbelow20percent.Inaddition,foreveryproject,theevolutionofthetrendofthetestssuccessversusfailureratioisdisplayedinachart.Afailingtestchartisreproducedhere:

Inthiscase,wecanseehowatbuild9,fourtestswherebroken,threewherefixedinbuild10,andthefinaloneinbuild11.

Toseehowaprojectstatuschangesbyforcingafailure,let’saddafailingtestsuchasthefollowing.Don’tforgettopushyourcommittotriggertheCIbuildasfollows:

publicfinalvoidtestForceFailure(){

fail("failtestisfail");

}

YetanotherveryinterestingfeaturethatisworthmentioningistheabilityofJenkinstokeepanddisplaythetimelineandbuildthetimetrend,asshowninthefollowingscreenshot:

Page 254: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thispagepresentsthebuildhistorywithlinkstoeveryparticularbuildthatyoucanfollowtoseethedetails.Nowwehavelesstobeworriedaboutandeverytimesomebodyinthedevelopmentteamcommitschangestotherepository,weknowthatthesechangeswillbeimmediatelyintegratedandthewholeprojectwillbebuiltandtested.IfwefurtherconfigureJenkins,wecanevenreceivethestatusbye-mail.Toachievethis,enableE-mailNotificationinthejobconfigurationpageandenterthedesiredRecipients.

Page 255: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 256: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryThischapterintroducedcontinuousintegrationinpracticeprovidingvaluableinformationtostartapplyingitsoontoyourprojectsnomatterwhattheirsize,whetheryouaredevelopingsoloorapartofabigcompanyteam.

ThetechniquespresentedfocusontheparticularitiesofAndroidprojectsmaintainingandsupportingwidelyuseddevelopmenttoolssuchasAndroidStudioandtheAndroidGradleplugin.

Weintroducedreal-worldexampleswithreal-worldtoolsavailablefromthevastopensourcearsenal.WeemployedGradletoautomatethebuildingprocess,Gittocreateasimpleversioncontrolsystemrepositorytostoreoursourcecodeandmanagethechanges,andfinally,installedandconfiguredJenkinsasthecontinuousintegrationofchoice.

WithinJenkins,wedetailedthecreationofjobstoautomatethecreationofourAndroidapplicationanditstests,andweemphasizedtherelationshipbetweenthecontinuousintegrationboxanditsdevices/emulators.

Finally,webecameawareoftheAndroid-connectedtestsresultsandimplementedastrategytoobtainanattractiveinterfacetomonitortherunningoftests,theirresults,andtheexistingtrends.

ThenextchaptertakesusthroughtheroadofTest-drivenDevelopment;you’llfinallystarttounderstandwhyIkeeptalkingaboutthetemperatureinalltheexamplessofarwithareal-worldproject.Thus,havingacontinuousintegrationsetupisperfecttoempowerustowritegreatcodeandhavefaithinourCIbuiltAPKsbeingreadytorelease.

Page 257: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 258: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter6.PracticingTest-drivenDevelopmentThischapterintroducestheTest-drivenDevelopment(TDD)discipline.WewillstartwithTDDpracticesinthegeneralsense,andlateronmovetotheconceptsandtechniquesmorecloselyrelatedtotheAndroidplatform.

Thisisacode-intensivechapter,sobepreparedtotypeasyouread,whichwouldhelpyougetthemostoutoftheexamplesprovided.

Inthischapter,wewilllearnthefollowingtopics:

IntroducingandexplainingTest-drivenDevelopmentAnalyzingitsadvantagesIntroducingareal-lifeexampleUnderstandingprojectrequirementsbywritingtestsEvolvingthroughtheprojectbyapplyingTDDGettinganapplicationthatfullycomplieswiththerequirements

Page 259: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GettingstartedwithTDDBriefly,Test-drivenDevelopmentisthestrategyofwritingtestsinparallelwiththedevelopmentprocess.Thesetestcasesarewritteninadvanceofthecodethatissupposedtosatisfythem.

Asingletestiswritten,andthenthecodeneededtosatisfythecompilationofthistestiswritten,thenthebehaviorthatthetestdecreesshouldexistiswritten.Wecontinuewritingtestsandimplementationuntilthefullsetofdesiredbehaviorsischeckedbythetests.

Thiscontrastswithotherapproachestothedevelopmentprocess,wherethetestsarewrittenattheendwhenallthecodinghasbeendone.

Writingthetestsinadvanceofthecodethatsatisfiesthemhasthefollowingadvantages:

Testsgetwrittenonewayoranother,whileifthetestsarelefttilltheenditishighlyprobablethattheywillneverbewrittenDeveloperstakemoreresponsibilityforthequalityoftheirwork,whenhavingtoconsiderthetestsastheycode

Designdecisionsaretakeninsmallerstepsandafterwardsthecodesatisfyingthetestsisimprovedbyrefactoring.Remember,thisiswhilehavingthetestsrunning,sothattherearenoregressionsinexpectedbehavior.

Test-drivenDevelopmentisoftenexplainedinadiagramlikethefollowing,tohelpusunderstandtheprocess:

ThefollowingsectionsexpandontheindividualactionsassociatedwiththeTDD,red,

Page 260: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

green,refactorcycle.

Page 261: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WritingatestcaseWestartourdevelopmentprocesswithwritingatestcase.Thisapparentlyisasimpleprocessthatwillputsomemachinerytoworkinsideourheads.Afterall,itisnotpossibletowritesomecode,testitornot,ifwedon’thaveaclearunderstandingoftheproblemdomain,anditsdetails.Usually,thisstepwillgetyoufacetofacewiththeaspectsoftheproblemyoudon’tunderstand,andyouneedtograsptheseifyouwanttomodelandwritethecode.

Page 262: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningalltestsOncethetestiswrittenthenextstepistorunit,alongwithallothertestswehavewrittensofar.Here,theimportanceofanIDEwithbuilt-insupportofthetestingenvironmentisperhapsmoreevidentthaninothersituations,cuttingthedevelopmenttimebyagoodfraction.Itisexpectedthat,firstly,ournewlywrittentestfailsaswestillhaven’twrittenanycode.

Tobeabletocompleteourtest,wewriteadditionalcodeandtakedesigndecisions.Theadditionalcodewrittenistheminimumpossibletogetourtesttocompile.Considerhere,thatnotcompilingisfailing.

Whenwegetthetesttocompileandrun,andifthetestfails,thenwetrytowritetheminimumamountofcodenecessarytomakethetestsucceed.Thismaysoundawkwardatthispoint,butthefollowingcodeexampleinthischapterwillhelpyouunderstandtheprocess.

Optionally,insteadofrunningalltestsagainyoucanjustrunthenewlyaddedtestsfirst,tosavesometimeassometimesrunningthetestsontheemulatorcouldberatherslow.Thenrunthewholetestsuitetoverifythateverythingisstillworkingproperly.Wedon’twanttoaddanewfeaturebybreakinganyfeaturesalreadyexistinginourcode.

Page 263: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RefactoringthecodeWhenthetestsucceeds,werefactorthecodeaddedtokeepittidy,clean,andtheminimalneededforamaintainableandextensibleapplication.

Werunallthetestsagain,toverifythatourrefactoringhasnotbrokenanything,andifthetestsareagainsatisfiedandnomorerefactoringisneeded,wefinishourtask.

Runningthetestsafterrefactoringisanincrediblesafetynetthathasbeenputinplacebythismethodology.Ifwemadeamistakerefactoringanalgorithm,extractingvariables,introducingparameters,changingsignatures,orwhatevertherefactoringmechanism,thistestinginfrastructurewilldetecttheproblem.Furthermore,ifsomerefactoringoroptimizationcouldnotbevalidforeverypossiblecase,wecanverifyitforeverycaseusedbytheapplicationexpressingthisasatestcase.

Page 264: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AdvantagesofTDDPersonally,themainadvantageI’veseensofaristhatitquicklyfocusesyouonyourprogramminggoal,anditishardertogetdistractedoreager,andimplementoptionsinyoursoftwarethatwillneverbeused(sometimesknownasgoldplating).Thisimplementationofunneededfeaturesisawasteofyourpreciousdevelopmenttimeandasyoumayalreadyknow,judiciouslyadministeringtheseresourcesmaybethedifferencebetweensuccessfullyreachingtheendoftheprojectornot.

Theotheradvantageisthatyoualwayshaveasafetynetforyourchanges.Everytimeyouchangeapieceofcode,youcanbeabsolutelysurethatotherpartsofthesystemarenotaffected,aslongastherearetestsverifyingthattheconditionshaven’tchanged.

Don’tforget,TDDcannotbeindiscriminatelyappliedtoanyproject.Ithinkthat,aswellasanyothertechnique;youshoulduseyourjudgmentandexpertisetorecognizewhereitcanbeappliedandwherenot.Alwaysremember:therearenosilverbullets.

Page 265: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

UnderstandingtherequirementsTobeabletowriteatestaboutanysubject,weshouldfirstunderstandthesubjectundertest,thismeansbreakingaparttherequirementyouareattemptingtoimplement.

Wementionedthatoneoftheadvantagesisthatyoufocusuponagoalquickly,insteadofrevolvingaroundtherequirementsasabig,unconquerablewhole.

Translatingrequirementsintotestsandcrossreferencingthemisperhapsthebestwaytounderstandtherequirements,andtobesurethatthereisalwaysanimplementationandverificationforallofthem.Also,whentherequirementschange(somethingthatisveryfrequentinsoftwaredevelopmentprojects),wecanchangethetestsverifyingtheserequirements,andthenchangetheimplementationtobesurethateverythingwascorrectlyunderstoodandmappedtothecode.

Page 266: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 267: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Creatingasampleproject–thetemperatureconverterYoumighthaveguesseditfromsomeofthecodesnippetssofar,thatourTDDexampleswillrevolvearoundanextremelysimpleAndroidsampleproject.Itdoesn’ttrytoshowallthefancyAndroidfeatures,butfocusesontestingandgraduallybuildingtheapplicationfromthetest,applyingtheconceptslearnedbefore.

Let’spretendthatwehavereceivedalistofrequirementstodevelopanAndroidtemperatureconverterapplication.Thoughoversimplified,wewillbefollowingthestepsyounormallywould,todevelopsuchanapplication.However,inthiscasewewillintroducetheTest-drivenDevelopmenttechniquesintheprocess.

Page 268: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ListofrequirementsUsually(let’sbehonest),thelistofrequirementsareveryvague,andthereareahighnumberofdetailsnotfullycovered.

Asanexample,let’spretendthatwereceivethislist:

TheapplicationconvertstemperaturesfromCelsiustoFahrenheitandvice-versaTheuserinterfacepresentstwofieldstoenterthetemperatures;oneforCelsiustheotherforFahrenheitWhenatemperatureisenteredinonefield,theotheroneisautomaticallyupdatedwiththeconversionIfthereareerrors,theyshouldbedisplayedtotheuser,possiblyusingthesamefieldsSomespaceintheuserinterfaceshouldbereservedfortheon-screenkeyboard,toeasetheapplicationoperationwhenseveralconversionsareenteredEntryfieldsshouldstartemptyValuesenteredaredecimalvalueswithtwodigitsafterthepointDigitsarerightalignedLastenteredvaluesshouldberetainedevenaftertheapplicationispaused

Page 269: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

UserinterfaceconceptdesignLet’sassumethatwereceivethisconceptualuserinterfacedesignfromtheuserinterfacedesignteam(Iapologizerightnowtoalldesignersformylackofimaginationandskill):

CreatingtheprojectOurfirststepistocreatetheproject.Now,sincewehavedonethisforfivechaptersalreadyIdon’tthinkIneedtogiveyouastep-by-stepguide.JustrunthroughtheAndroidStudionewprojectwizard,andselectanAndroidmobileprojectwithyourpackagename,plusotherboilerplate,andnoActivitytemplate.AndroidStudiowillautomaticallycreateyouanexampleAndroidApplicationTestCase.Bearinmind,ifyougetstuck,youcanrefertothecodeaccompanimentforthisbook.Whencreated,itshouldlooksomethinglikethis:

Page 270: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Nowlet’squicklycreateanewActivitycalledTemperatureConverterActivity(wedidn’tusethetemplategenerator,becauseitaddsloadsofcodethatisnotneededrightnow),don’tforgettoaddtheActivitytoyourAndroidManifestfile.FanaticTDD’ersmightbeshakingtheirfistrightnow,asreallyyoushouldmakethisActivityonlywhenneededinyourtests,butI’mtryingtoguideyouwithsomefamiliarityatthesametime.

Page 271: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 272: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingaJavamoduleOntopofthistemplateproject,wewanttoaddanothermoduleofcode.ThiswillbeaJava-onlymoduleandwillactasadependencyorlibrary,ifyouwill,forourmainAndroidmodule.

Theideahereistwo-fold.First,itallowsyoutoseparatecodethatisJavaonly,anddoesnothaveadependencyonAndroid,inabigprojectthiscanbeyourcoredomain;thebusinesslogicthatrunsyourapp,anditisimportantthatyoumodularizethis,soyoucanworkonitwithouthavingtothinkaboutAndroidaswell.

Secondly,havingaJava-onlymoduleaswe’vesaidbefore,allowsyoutocallonthevasthistoryofJavaasanestablishedprogramminglanguagewhenitcomestotesting.TestingoftheJavamoduleisfast,simple,andeasy.YoucanwriteJUnittestsfortheJVMandhavethemrunninginmilliseconds(whichwewilldo!).

FromAndroidStudio,navigatetoFile|NewModule,thisgivesyoutheCreatenewmoduledialog.UnderMoreModules,selectJavaLibrary,andhitNext.Nameyourlibrarycore,andensurethepackagenameisthesameasyourAndroidapplication,andpressonFinish.Thelastscreenshouldhavelookedsomethinglikethis:

Oncecreated,youneedtoaddtheone-waydependencyfromyourAndroid:appmoduletothe:coremodule.Within,/app/build.gradle,addthedependencyoncore:

Page 273: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

dependencies{

compilefileTree(dir:'libs',include:['*.jar'])

compile'com.android.support:appcompat-v7:21.0.2'

compileproject(':core')

}

ThisallowsustoreferencefilesfromourcoremoduleinsideofourAndroidapplication.

Page 274: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 275: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingtheTemperatureConverterActivityTestsclassProceedwithcreatingthefirsttestbyselectingthemaintestpackagename,com.blundell.tut.Thisisundersrc/androidTest/JavaintheAndroidStudioprojectview,orunderapp/java/(androidTest)intheAndroidStudioAndroidview.Thenright-clickhere,andselectNew|JavaClass,callit,TemperatureConverterActivityTests.

Oncetheclassiscreated,weneedtogoaboutturningitintoatestclass.Weshouldselectoursuperclassdependingonwhatandhowwearegoingtotest.InChapter2,UnderstandingTestingwiththeAndroidSDK,wereviewedtheavailablealternatives.Useitasareferencewhenyoutrytodecidewhatsuperclasstouse.

Inthisparticularcase,wearetestingasingleActivityandusingthesysteminfrastructure,therefore,weshoulduseActivityInstrumentationTestCase2.AlsonotethatasActivityInstrumentationTestCase2isagenericclass,weneedthetemplateparameteraswell.ThisistheActivityundertest,whichinourcase,isTemperatureConverterActivity.

Wenownoticethatourclasshassomeerrorsweneedtofixbeforerunning.Otherwisetheerrorswillpreventthetestfromrunning.

TheproblemweneedtofixhasbeendescribedbeforeinChapter2,UnderstandingTestingwiththeAndroidSDK,undertheTheno-argumentconstructorsection.Asthispatterndictates,weneedtoimplement:

publicTemperatureConverterActivityTests(){

this("TemperatureConverterActivityTests");

}

publicTemperatureConverterActivityTests(Stringname){

super(TemperatureConverterActivity.class);

setName(name);

}

Sofarwehaveperformedthefollowingsteps:

WeaddedthenoargumentconstructorTemperatureConverterActivityTests().Fromthisconstructor,weinvoketheconstructorthattakesanameasaparameter.Finally,inthisgivennameconstructor,weinvokethesuperconstructorandsetthename.

Toverifythateverythinghasbeensetupandisinplace,youmayrunthetestsbyrightclickingontheclass,andselectingRun|TheNameoftheTestClass.Therearenoteststorunyet,butatleastwecanverifythattheinfrastructuresupportingourtestsisalreadyinplace.ItshouldfailwithaNotestsfoundwarning.Hereishowtorunthetestclass,incaseyoumissedit:

Page 276: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 277: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingthefixtureWecanstartcreatingourtestfixturebypopulatingthesetup()methodwiththeelementsweneedinourtests.Almostunavoidable,inthiscase,istheuseoftheActivityundertest,solet’sprepareforthesituationandaddittothefixture:

@Override

publicvoidsetUp()throwsException{

super.setUp();

activity=getActivity();

}

Afterintroducingthepreviouscode,createtheactivityfieldusingAndroidStudio’srefactoringtoolstosaveyoutime.(F2fornexterror,Alt+Enterforquickfix,Enteragaintocreatefield,Enteragaintoconfirmthefieldstype,done!)

TheActivityInstrumentationTestCase2.getActivity()methodhasasideeffect.IftheActivityundertestisnotrunning,itwillbestarted.ThismaychangetheintentionofatestifweusegetActivity()asasimpleaccessorseveraltimesinatest,andforsomereasontheActivityfinishesorcrashesbeforetestcompletion.WewillbeinadvertentlyrestartingtheActivity,thatiswhyinourtestswediscouragetheuseofgetActivity()infavorofhavingitinthefixture,sothatweareimplicitlyrestartingtheactivityforeverytest.

Page 278: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingtheuserinterfaceBacktoourTest-drivenDevelopmenttrack,weseefromourconciselistofrequirementsthattherearetwoentriesforCelsiusandFahrenheittemperatures,respectively.Solet’saddthemtoourtestfixture.

Theydon’texistyet,andwehaven’tevenstarteddesigningtheuserinterfacelayout,butweknowthatthereshouldbetwoentriesliketheseforsure.

ThisisthecodeyoushouldaddtothesetUp()method:

celsiusInput=(EditText)

activity.findViewById(R.id.converter_celsius_input);

fahrenheitInput=(EditText)

activity.findViewById(R.id.converter_fahrenheit_input);

Therearesomeimportantthingstonotice:

Wechoosethenamesconverter_celsius_inputbecause,converter_isthelocationofthisfield(intheTemperatorConverterActivity)celsius_iswhatthefieldrepresents,andfinallyinputishowthefieldsbehaveWedefinethefieldsforourfixtureusingEditTextWeusethepreviouslycreatedActivitytofindtheViewsbyIDWeusetheRclassforthemainprojecteventhoughtheseIDsdonotexist

Page 279: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TestingtheexistenceoftheuserinterfacecomponentsOncewehaveaddedthemtothesetUp()method,asindicatedintheprevioussection,wecanwriteourfirsttestandchecktheviewsexistence:

publicfinalvoidtestHasInputFields(){

assertNotNull(celsiusInput);

assertNotNull(fahrenheitInput);

}

Wearenotabletorunthetestsyetbecausewemustfixsomecompilationproblemsfirst.WeshouldfixthemissingIDsintheRclass.

HavingcreatedourtestfixturethatreferenceselementsandIDsintheuserinterfacethatwedon’thaveyet,it’smandatedbytheTest-drivenDevelopmentparadigmthatweaddtheneededcodetosatisfyourtests.Thefirstthingweshoulddoisgetthetesttocompile,soifwehavesometeststestingunimplementedfeatures,theywillfail.

Page 280: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GettingtheIDsdefinedOurfirststopwouldbetohavetheIDsfortheuserinterfaceelementsdefinedintheRclass,sotheerrorsgeneratedbyreferencingundefinedconstantsR.id.converter_celsius_inputandR.id.converter_fahrenheit_inputgoaway.

You,asanexperiencedAndroiddeveloper,willknowhowtodoit.I’llgiveyouarefresheranyway.Createanactivity_temperature_converter.xmllayoutinthelayouteditor,andaddtherequireduserinterfacecomponentstogetsomethingthatresemblesthedesignpreviouslyintroducedintheUserInterfaceconceptdesignsection,asshowninthefollowingcode:

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginBottom="@dimen/margin"

android:text="@string/message"/>

<<TextView

android:id="@+id/converter_celsius_label"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginStart="@dimen/margin"

android:text="@string/celsius"/>

<EditText

android:id="@+id/converter_celsius_input"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="@dimen/margin"/>

<TextView

android:id="@+id/converter_fahrenheit_label"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginStart="@dimen/margin"

android:text="@string/fahrenheit"/>

<EditText

android:id="@+id/converter_fahrenheit_input"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="@dimen/margin"/>

</LinearLayout>

Doingso,wegetourteststocompile(don’tforgettoaddthestringsanddimensions),runthetests,dotheypass?Theyshouldn’t!Youneedtohookupyournewactivitylayout(I

Page 281: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

betyoubeatmetoit):

publicclassTemperatureConverterActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_temperature_converter);

}

}

Runthetestsoncemore,andyoushouldgetthefollowingresult:

ThetestHasInputFieldstestsucceededEverythingisgreennow

Theoutputofthetestisseenasfollows:

ThisclearlymeansthatweareontrackwithapplyingTDD.

Youmayalsohavenoticedthatweaddedsomedecorativeandnon-functionalitemstoouruserinterfacethatwearenottesting(saypadding),mainlytokeepourexampleassimpleaspossible.Inareal-casescenario,youmaywanttoaddtestsfortheseelementstoo.

Page 282: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TranslatingrequirementstotestsTestshaveadoublefeature.Theyverifythecorrectnessofourcodebut,sometimes,andmoreprominentlyinTDD,theyhelpusunderstandthedesignanddigestwhatweareimplementing.Tobeabletocreatethetests,weneedtounderstandtheproblemwearedealingwith,andifwedon’t,weshouldatleasthavearoughoutlineoftheproblemtoallowustostarttohandleit.

Manytimes,therequirementsbehindtheuserinterfacearenotclearlyexpressed,butyoushouldbeabletounderstandthemfromthewireframedUIdesign.Ifwepretendthatthisisthecase,thenwecangraspthedesignbywritingourtestsfirst.

EmptyfieldsFromoneofourrequirements,weget:Entryfieldsshouldstartempty.

Toexpressthisinatest,wecanwritethefollowing:

publicvoidtestFieldsShouldStartEmpty(){

assertEquals("",celsiusInput.getText().toString());

assertEquals("",fahrenheitInput.getText().toString());

}

Here,wesimplycomparetheinitialcontentsofthefieldsagainsttheemptystring.

Thistestpassesstraightaway,great!AlthoughatenantofTDDalwaysstartswitharedtest,youmightwanttodoaquicksanitycheck,andaddsometexttotheXMLforEditTextandrunthetests,andwhenitgoesredandgreenagainwhenyouremovetheaddedtext,youknowyourtestisvalidatingthebehavioryouexpect(anditwasn’tgreenasasideeffectofsomethingyoudidnotexpect).Wesuccessfullyconvertedonerequirementtoatest,andvalidateditbyobtainingthetestresults.

ViewpropertiesIdentically,wecanverifyotherpropertiesoftheViewscomposingourlayout.Amongotherthings,wecanverify:

Fields(appearonthescreenasexpected)FontsizesMarginsScreenalignment

Let’sstartverifyingthatthefieldsareonthescreen:

publicvoidtestFieldsOnScreen(){

Vieworigin=activity.getWindow().getDecorView();

assertOnScreen(origin,celsiusInput);

assertOnScreen(origin,fahrenheitInput);

}

Asexplainedbefore,weuseanassertfromhere:ViewAsserts:assertOnScreen.

Page 283: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

NoteStaticimportsandhowtomakethemostofthemwasexplainedinChapter2,UnderstandingTestingwiththeAndroidSDK.Ifyouhaven’tdoneitbefore,nowisthetime.

TheassertOnScreen()methodneedsanorigintostartlookingfortheotherViews.Inthiscase,becausewewanttostartfromthetop-mostlevel,weusegetDecorView(),whichretrievesthetop-levelwindowviewcontainingthestandardwindowframeanddecorations,withtheclient’scontentinside.

Byrunningthistest,wecanensurethattheentryfieldsareonthescreen,astheUIdesigndictates.Insomeway,wealreadyknewthatViews,withthesespecificIDs,existed.Thatis,wemadethefixturecompilebyaddingtheViewstothemainlayout,butwewerenotsuretheywereappearingonthescreenatall.So,nothingelseisneededbutthesolepresenceofthistest,toensurethattheconditionisnotchangedinthefuture.Ifweremoveoneofthefieldsforsomereason,thistestwilltellusthatitismissing,andnotcomplyingwiththeUIdesign.

Followingwithourlistofrequirements,weshouldtestthattheViewsarealignedinthelayoutasweexpect:

publicvoidtestAlignment(){

assertLeftAligned(celsiusLabel,celsiusInput);

assertLeftAligned(fahrenheitLabel,fahrenheitInput);

assertLeftAligned(celsiusInput,fahrenheitInput);

assertRightAligned(celsiusInput,fahrenheitInput);

}

WecontinueusingassertsfromViewAssert—inthiscase,assertLeftAlignedandassertRightAligned.ThesemethodsverifythealignmentofthespecifiedViews.TogetthistestrunningwehavetoaddthetwolookupsforthelabelTextView’sinthesetUp()method:

celsiusLabel=(TextView)

activity.findViewById(R.id.converter_celsius_label);

fahrenheitLabel=(TextView)

activity.findViewById(R.id.converter_fahrenheit_label);

TheLinearLayoutclassweareusingbydefaultarrangesthefieldsinthewayweareexpectingthem.Again,whilewedon’tneedtoaddanythingtothelayout,tosatisfythetest,thiswillactasaguardcondition.

Oncewe’veverifiedthattheyarecorrectlyaligned,weshouldverifythattheyarecoveringthewholescreenwidth,asspecifiedbytheschematicdrawing.Inthisexample,it’ssufficienttoverifyLayoutParamshavingthecorrectvalues:

publicvoidtestCelciusInputFieldCoversEntireScreen(){

LayoutParamslp;

intexpected=LayoutParams.MATCH_PARENT;

lp=celsiusInput.getLayoutParams();

assertEquals("celsiusInputlayoutwidthisnotMATCH_PARENT",

Page 284: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

expected,lp.width);

}

publicvoidtestFahrenheitInputFieldCoversEntireScreen(){

LayoutParamslp;

intexpected=LayoutParams.MATCH_PARENT;

lp=fahrenheitInput.getLayoutParams();

assertEquals("fahrenheitInputlayoutwidthisnotMATCH_PARENT",

expected,lp.width);

}

Weusedacustommessagetoeasilyidentifytheproblem,incasethetestfails.

Byrunningthistest,weobtainthefollowingmessageindicatingthatthetestfailed:AssertionFailedError:celsiusInputlayoutwidthisnotMATCH_PARENTexpected:<-1>butwas:<-2>.

Thisleadsustothelayoutdefinition.Wemustchangelayout_widthtobematch_parentfortheCelsiusandFahrenheitfields:

<EditText

android:id="@+id/converter_celsius_input"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="@dimen/margin"

android:gravity="end|center_vertical"/>

SameforFahrenheit—afterthechangeisdone,werepeatthecycle,andbyrunningthetestagain,wecanverifythatitisnowsuccessful.

Ourmethodisstartingtoappear.Wecreatethetesttoverifyaconditiondescribedintherequirements.Ifit’snotmet,wechangethecauseoftheproblem,andrunningthetestsagain,weverifythatthelatestchangesolvestheproblem,andwhatisperhapsmoreimportantisthatthechangedoesn’tbreaktheexistingcode.

Next,let’sverifythatthefontsizesaredefinedasperourrequirements:

publicvoidtestFontSizes(){

floatpixelSize=24f;

assertEquals(pixelSize,celsiusLabel.getTextSize());

assertEquals(pixelSize,fahrenheitLabel.getTextSize());

}

Retrievingthefontsizeusedbythefieldisenoughinthiscase.

Thedefaultfontsizeisnot24px,soweneedtoaddthistoourlayout.It’sagoodpracticetoaddthecorrespondingdimensiontoaresourcefile,andthenuseitwhereit’sneededinthelayout.So,let’saddlabel_text_sizetores/values/dimens.xml,withavalueof24sp.ThenreferenceitintheTextsizepropertyofthelabels,celsius_labelandfahrenheit_label.

Now,thetestmaypassoritmaynot,dependingontheresolutionofyourdeviceoremulatoryouareusing.Thisisbecauseweareassertinginthetest,thepixelsize,butwehavedeclaredinthedimens.xml,tousesp(scaleindependentpixels).Let’shardenthis

Page 285: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

test.Toresolvethiswecouldeitherconvertourpxtospinthetestclass,orusethespvalueinthetest.Ihavechosentousespinthetest,althoughyoucouldargueforeither:

publicvoidtestFontSizes(){

floatpixelSize=getFloatPixelSize(R.dimen.label_text_size);

assertEquals(pixelSize,celsiusLabel.getTextSize());

assertEquals(pixelSize,fahrenheitLabel.getTextSize());

}

privatefloatgetFloatPixelSize(intdimensionResourceId){

returngetActivity().getResources()

.getDimensionPixelSize(dimensionResourceId);

}

Finally,let’sverifythatmarginsareinterpretedasdescribedintheuserinterfacedesign:

publicvoidtestCelsiusInputMargins(){

LinearLayout.LayoutParamslp=

(LinearLayout.LayoutParams)celsiusInput.getLayoutParams();

assertEquals(getIntPixelSize(R.dimen.margin),lp.leftMargin);

assertEquals(getIntPixelSize(R.dimen.margin),lp.rightMargin);

}

publicvoidtestFahrenheitInputMargins(){

LinearLayout.LayoutParamslp=

(LinearLayout.LayoutParams)fahrenheitInput.getLayoutParams();

assertEquals(getIntPixelSize(R.dimen.margin),lp.leftMargin);

assertEquals(getIntPixelSize(R.dimen.margin),lp.rightMargin);

}

Thisisasimilarcaseasbefore(I’veskippedthestepoftestingtherawpixelvalue).Weneedtoaddthemargintoourlayout.Let’saddthemargindimensiontotheresourcefile,andthenuseitwhereit’sneededinthelayout.Setthemargindimensioninres/values/dimens.xmltoavalueof8dp.Then,referenceitinthelayout_margin_startpropertyofbothfields,celsiusandfahrenheit,andalsointhestartmarginofthelabels.

Thehelpermethodtogettheintegerpixelsizefromaresourcedimen,justwrapsthefloatmethodalreadydiscussed:

privateintgetIntPixelSize(intdimensionResourceId){

return(int)getFloatPixelSize(dimensionResourceId);

}

Onemorethingthatisleftistoverifythejustification(alignment)oftheenteredvalues.Wewillvalidatetheinputshortly,toallowonlythepermittedvalues,butfornowlet’sjustpayattentiontothejustification.Theintentionistohavevaluesthataresmallerthanthewholefield,justifiedtotherightandverticallycentered:

publicvoidtestCelsiusInputJustification(){

intexpectedGravity=Gravity.END|Gravity.CENTER_VERTICAL;

Page 286: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

intactual=celsiusInput.getGravity();

StringerrorMessage=String.format(

"Expected0x%02xbutwas0x%02x",expectedGravity,actual);

assertEquals(errorMessage,expectedGravity,actual);

}

publicvoidtestFahrenheitInputJustification(){

intexpectedGravity=Gravity.END|Gravity.CENTER_VERTICAL;

intactual=fahrenheitInput.getGravity();

StringerrorMessage=String.format(

"Expected0x%02xbutwas0x%02x",expectedGravity,actual);

assertEquals(errorMessage,expectedGravity,actual);

}

Here,weverifythegravityvaluesasusual.However,weareusingacustommessagetohelpusidentifythevaluesthatcouldbewrong.AstheGravityclassdefinesseveralconstantswhosevaluesarebetteridentifiedifexpressedinhexadecimal,weareconvertingthevaluestothisbaseinthemessage.

Ifthistestisfailingduetothedefaultgravityusedforthefields,thenwhatisonlyleftistochangeit.Gotothelayoutdefinitionandalterthesegravityvalues,sothatthetestsucceeds.

Thisispreciselywhatweneedtoadd:

android:gravity="end|center_vertical"

Page 287: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ScreenlayoutWenowwanttoverifythattherequirementspecifyingthatenoughscreenspaceshouldbereservedtodisplaythekeyboard,isactuallyfulfilled.

Wecanwriteatestlikethis:

publicvoidtestVirtualKeyboardSpaceReserved(){

intexpected=getIntPixelSize(R.dimen.keyboard_space);

intactual=fahrenheitInput.getBottom();

StringerrorMessage=

"Spacenotreserved,expected"+expected+"actual"+actual;

assertTrue(errorMessage,actual<=expected);

}

Thisverifiesthattheactualpositionofthelastfieldinthescreen,whichisfahrenheitInput,isnotlowerthanasuggestedvalue.

Wecanrunthetestsagainverifyingthateverythingisgreenagain.Runupyourapplication,andyoushouldhaveacompleteuserinterfacebackedbytests,asshowninthefollowingscreenshot:

Page 288: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 289: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 290: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AddingfunctionalityTheuserinterfaceisinplace.Now,wecanstartaddingsomebasicfunctionality.Thisfunctionalitywillincludethecodetohandletheactualtemperatureconversion.

Page 291: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TemperatureconversionFromthelistofrequirements,wecanobtainthisstatement:Whenonetemperatureisenteredinonefield,theotheroneisautomaticallyupdatedwiththeconversion.

Followingourplan,wemustimplementthisasatesttoverifythatthecorrectfunctionalityisthere.Ourtestwouldlooksomethinglikethis:

@UiThreadTest

publicvoidtestFahrenheitToCelsiusConversion(){

celsiusInput.clear();

fahrenheitInput.clear();

fahrenheitInput.requestFocus();

fahrenheitInput.setText("32.5");

celsiusInput.requestFocus();

doublef=32.5;

doubleexpectedC=TemperatureConverter.fahrenheitToCelsius(f);

doubleactualC=celsiusInput.getNumber();

doubledelta=Math.abs(expectedC-actualC);

Stringmsg=""+f+"F->"+expectedC+"Cbutwas"

+actualC+"C(delta"+delta+")";

assertTrue(msg,delta<0.005);

}

Let’srunthroughthisstep-by-step:

1. Firstly,aswealreadyknow,tointeractwiththeUIchangingitsvaluesweshouldrunthetestontheUIthread,andthusbecauseweuseEditText.setText,thetestisannotatedwith@UiThreadTest.

2. Secondly,weareusingaspecializedclasstoreplaceEditTextprovidingsomeconveniencemethodssuchasclear()andsetNumber().Thiswillimproveourapplicationdesign.

3. Next,weinvokeaconverter,namedTemperatureConverter,autilityclassprovidingthedifferentmethodstoconvertbetweendifferenttemperatureunits,andusingdifferenttypesforthetemperaturevalues.

4. Finally,aswewillbetruncatingtheresultstoprovidetheminasuitableformatpresentedintheuserinterface,weshouldcompareagainstadeltatoassertthevalueoftheconversion.

Creatingthetestlikethiswillforceustofollowtheplannedpath.Ourfirstobjectiveistoaddtheneededmethodsandcodetogetthetesttocompile,andthentosatisfythetest’sneeds.

Page 292: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheEditNumberclassInourmainpackage,notinthetestsone(whichisnottheoneunder/androidTest/),weshouldcreatetheEditNumberclassextendingEditText,asweneedtoextenditsfunctionality.Oncetheclassiscreated,weneedtochangethetypeofthefieldsinourtestclassmembertypes:

publicclassTemperatureConverterActivityTestsextends

ActivityInstrumentationTestCase2<TemperatureConverterActivity>{

privateTemperatureConverterActivityactivity;

privateEditNumbercelsiusInput;

privateEditNumberfahrenheitInput;

privateTextViewcelsiusLabel;

privateTextViewfahrenheitLabel;

Then,changeanycastthatispresentinthetests.YourIDEwillhighlightthese;pressF2tofindthemintheclass.

Therearestilltwoproblemsweneedtofixbeforebeingabletocompilethetest:

Westilldon’thavetheclear()andsetNumber()methodsinEditNumberWedon’thavetheTemperatureConverterutilityclass

Frominsideourtestclass,wecanusetheIDEtohelpuscreatethemethods.PressF2again,andyoushouldbetakentotheerrorforCannotresolvemethodclear().NowpressAlt+Entertocreatetheclear()methodintypeEditNumber.SameforgetNumber().

Finally,wemustcreatetheTemperatureConverterclass.ThisclasswillholdthemathematicalconversionsofCelsiusandFahrenheit,andnoAndroidcode.Therefore,wecancreatethispackageinsideofour/core/module.Aspreviouslydiscussed,itwillbeunderthesamepackagestructure,onlythismoduledoesnotknowaboutAndroidand,therefore,wecanwriteJVMteststhatrunmuchfaster.

TipBesuretocreateitinthecoremoduleunderthesamepackageasyourmaincode,andnotinthetestpackage.

Here’showtocreatethatclassinthecoremodule,andthecurrentstateofourapplication:

Page 293: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Havingdonethis,inourtest,itcreatesthefahrenheitToCelsiusmethod.

Thisfixesourlastproblem,andleadsustoatestthatwecannowcompileandrun.YesyouwillhaveredLinterrors,butthesearenot“compile”errors,andsothetestscanstillrun.(AndroidStudio’sclevernessistoodamnhigh.)

Surprisingly,ornot,whenwerunthetests,theywillfailwithanexception:

java.lang.ClassCastException:

android.widget.EditTextcannotbecasttocom.blundell.tut.EditNumber

atcom.blundell.tut.TemperatureConverterActivityTests.setUp(

TemperatureConverterActivityTests.java:36)

atandroid.test.AndroidTestRunner.runTest(

AndroidTestRunner.java:191)

ThatisbecauseweupdatedallofourJavafilestoincludeournewlycreatedEditNumberclass,butforgottochangethelayoutXML.

Let’sproceedtoupdateourUIdefinition:

<com.blundell.tut.EditNumber

android:id="@+id/converter_celsius_input"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="@dimen/margin"

android:gravity="end|center_vertical"/>

Page 294: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thatis,wereplacetheoriginalEditTextclassbycom.blundell.tut.EditNumber,whichisaViewextendingtheoriginalEditTextclass.

Now,werunthetestsagain,andwediscoverthatalltestspass.

Butwaitaminute;wehaven’timplementedanyconversionoranyhandlingofvaluesinthenewEditNumberclass,andalltestspassedwithnoproblem.Yes,theypassedbecausewedon’thaveenoughrestrictionsinoursystemandtheonesinplace,simplycancelthemselves.

Beforegoingfurther,let’sanalyzewhatjusthappened.OurtestinvokedthefahrenheitInput.setText("32.5")methodtosetthetemperatureenteredintheFahrenheitfield,butourEditNumberclassdoesn’tdoanythingwhentextisentered,andthefunctionalityisnotimplemented.So,theCelsiusfieldremainsempty.

ThevalueforexpectedC—theexpectedtemperatureinCelsius,iscalculatedinvokingTemperatureConverter.fahrenheitToCelsius(f),butthisisanemptymethod.Inthiscasebecauseweknewthereturntypeofthemethodwemadeitreturntoaconstant0.So,expectedCbecomes0.

Then,theactualvaluefortheconversionisobtainedfromtheUI.InthiscaseinvokinggetNumber()fromEditNumber.Butthismethodwasautomaticallygenerated,andtosatisfytherestrictionimposedbyitssignature,itmustreturnavalue,namely0.

Thedeltavalueisagain0,ascalculatedbyMath.abs(expectedC–actualC).

AndfinallyourassertionassertTrue(msg,delta<0.005)istrue,becausedelta=0satisfiesthecondition,andthetestpasses.

So,isourmethodologyflawed,asitcannotdetectasimplesituationlikethis?

No,notatall,theproblemhereisthatwedon’thaveenoughrestrictions,andtheyaresatisfiedbythedefaultvaluesusedbyauto-generatedmethods.Onealternativecouldbetothrowexceptionsatalloftheauto-generatedmethods,somethinglikeRuntimeException("notyetimplemented")todetectitsusewhennotimplemented.Wewillbeaddingenoughrestrictionsinoursystemtoeasilytrapthisdoublezerocondition.

Page 295: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheTemperatureConverterunittestsItseems,fromourpreviousexperience,thatthedefaultconversionimplementedalwaysreturns0,soweneedsomethingmorerobust.Otherwise,ourconverterwillonlybereturningavalidresult,whentheparametertakesthevalueof32F(32F==0C).

TheTemperatureConverterclassisautilityclassnotrelatedwiththeAndroidinfrastructure,soastandardunittestwillbeenoughtotestit.

Asthisisthefirstcoretestwearegoingtowrite,weneedtodosomesetup.Firstly,fromtheprojectview;inyourprojectstructurecreateatestfolderunder/core/srcbyselectingNew|Directoryandusingthenametest.Insidethis,createajavafolderbyselectingNew|Directory,andusingthenamejava.WithGradlebeingmagic,itwillnowunderstandthatthisisaplaceyouwanttoaddtests,andthefoldershouldturngreen(greenmeansthatthefolderisapartofthetestclasspath).Nowaddanewpackage,technicallyitisnotnewbecausewearegoingtousecom.blundell.tutagain,byselectingNew|Package|andusingthenamecom/blundell/tut.

Now.wecreateourtestsinournewfolderandpackage.WecreateourtestsbyselectingNew|JavaClass,andcallingitTemperatureConverterTests.Yourprojectshouldnowlooklikethis:

Let’smakeourfirsttest,insideofTemperatureConverterTests,pressCtrl+EntertobringuptheGeneratemenu,asshowninthefollowingscreenshot:

Page 296: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SelectingtheTestMethodtest,thenJUnit4willgenerateusatemplatemethodofatestthatwewant,nameittestFahrenheitToCelsius().Rememberthisshortcutasit’shandywhenevercreatinganewtest.Onceyou’vegeneratedthistest,you’llnoticewehavecompileerrorsontheJUnit4importedlinesofcode.Oops!weforgottoaddtheJUnitlibrarytothetestclasspathofourcoremodule.Openupthebuildfilein/core/build.gradle,andaddtheJUnitdependency.Yourcorebuild.gradlewillnowlooklikethis:

applyplugin:'java''java'

dependencies{

compilefileTree(dir:'libs''libs',include:[''''*.jar'])

testCompile'junit'junit:junit:4.+''''

}

NoteNotice,herewehavejumpedfromJUnit3toJUnit4themaindifferencebeingwecannowuseannotationstotellourtestrunner,whichofthemethodsintheclassaretests.Therefore,technicallywedon’tneedtostartthemethodswithtestasintestFooBar()anymore,butwewillforourownsanitywhenswoppingbetweenthetwo(AndroidJUnit4supportiscomingsoon!).

DoaprojectsyncbyselectingProjectSync,andwearecompilingandreadytocode.Let’sstartwritingthetest:

@Test

publicvoidtestFahrenheitToCelsius(){

Page 297: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

for(doubleknownCelsius:conversionTable.keySet()){

doubleknownFahrenheit=conversionTable.get(knownCelsius);

doubleresultCelsius=

TemperatureConverter.fahrenheitToCelsius(knownFahrenheit);

doubledelta=Math.abs(resultCelsius-knownCelsius);

Stringmsg=knownFahrenheit+"F->"+knownCelsius+"C"+"but

is"+resultCelsius;

assertTrue(msg,delta<0.0001);

}

}

Creatingaconversiontablewithvaluesfordifferenttemperatureconversion,weknowfromothersources,wouldbeagoodwaytodrivethistest:

Map<Double,Double>conversionTable=newHashMap<Double,Double>(){

//initialize(celsius,fahrenheit)pairs

put(0.0,32.0);

put(100.0,212.0);

put(-1.0,30.20);

put(-100.0,-148.0);

put(32.0,89.60);

put(-40.0,-40.0);

put(-273.0,-459.40);

}};

Toruntestsinthecoremodule,wecanrightclickonthefileintheprojectview,andselectRun.Asthescreenshotalsoshows,youcanusetheshortcutCmd+Shift+F10:

Page 298: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Whenthistestruns,weverifythatitfails,givingusthistrace:

java.lang.AssertionError:-40.0F->-40.0Cbutis0.0

atorg.junit.Assert.fail(Assert.java:88)

atorg.junit.Assert.assertTrue(Assert.java:41)

at

com.blundell.tut.TemperatureConverterTests.testFahrenheitToCelsius(Temperat

ureConverterTests.java:31).

NoteSeehowfastthosecoretestsran!Aimformovingasmuchofyourapplicationlogicintoyourcoremoduleasyoucan,soyoucantakeadvantageofthisspeedwhendoingTest-drivenDevelopment.

Well,thiswassomethingwewereexpectingasourconversionalwaysreturns0.Implementingourconversion,wediscoverthatweneedsomeABSOLUTE_ZERO_Fconstant:

privatestaticfinaldoubleABSOLUTE_ZERO_F=-459.67d;

privatestaticfinalStringERROR_MESSAGE_BELOW_ZERO_FMT=

"Invalidtemperature:%.2f%cbelowabsolutezero";

Page 299: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

privateTemperatureConverter(){

//non-instantiablehelperclass

}

publicstaticdoublefahrenheitToCelsius(doublefahrenheit){

if(fahrenheit<ABSOLUTE_ZERO_F){

Stringmsg=String.format(ERROR_MESSAGE_BELOW_ZERO_FMT,

fahrenheit,'F''F');

thrownewInvalidTemperatureException(msg);

}

return((fahrenheit-32)/1.8d);

}

Absolutezero,isthetheoreticaltemperatureatwhichentropywouldreachitsminimumvalue.Tobeabletoreachthisabsolutezerostate,accordingtothelawsofthermodynamics,thesystemshouldbeisolatedfromtherestoftheuniverse.Thus,itisanunreachablestate.However,byinternationalagreement,absolutezeroisdefinedas0KontheKelvinscale,andas-273.15°ContheCelsiusscaleorto-459.67°FontheFahrenheitscale.

Wearecreatingacustomexception,InvalidTemperatureException,toindicateafailureprovidingavalidtemperaturetotheconversionmethod.Thisexceptiondoesn’tknowanythingaboutAndroid,andsocanalsositinourcoremodule.CreateitbyextendingRuntimeException:

publicclassInvalidTemperatureExceptionextendsRuntimeException{

publicInvalidTemperatureException(Stringmsg){

super(msg);

}

}

Runningthecoretestsagain,wediscoverthattestFahrenheitToCelsiussucceeds.Therefore,wemovebacktoourAndroidtests,andrunningtheseshowussuchthattestFahrenheitToCelsiusConversiontestfails.Thistellsus,thatnowtheconverterclasscorrectlyhandlesconversions,buttherearestillsomeproblemswiththeUIhandlingthisconversion.

NoteDon’tdespairaboutrunningtwoseparatetestclasses.Itiscommonforyoutobeselectiveaboutwhatteststorun;thisispartlyalearntskillwhendoingTDD.However,ifyousowish,youcanwritecustomtestrunnersthatwillrunallofyourtests.Also,usingGradletorunbuildconnectedAndroidTestwillrunallyourtestsatonce,whichisadvisedwheneveryouconsideryouhavecompletedafeature,orwanttocommittoyourupstreamversioncontrol.

AcloserlookatthetestFahrenheitToCelsiusConversionfailuretracerevealsthatthere’ssomethingstillreturning0,whenitshouldn’t.

ThisremindsusthatwearestilllackingaproperEditNumberimplementation.Before

Page 300: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

proceedingtoimplementthementionedmethods,let’screatethecorrespondingteststoverifywhatweareimplementingiscorrect.

Page 301: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheEditNumbertestsFromthepreviouschapter,wecannowdeterminethatthebestbaseclassforourcustomViewtestsisAndroidTestCase,asweneedamockContextclasstocreatethecustomView,butwedon’tneedsysteminfrastructure.

CreatethetestsforEditNumber,let’scallitEditNumberTests,andextendAndroidTestCase.Reminder,thisisundertheappmoduleintheandroidTestpath.

Weneedtoaddtheconstructorstoreflectthepatternweidentifiedbeforewiththegivennamepattern:

publicEditNumberTests(){

this("EditNumberTests");

}

publicEditNumberTests(Stringname){

setName(name);

}

Thenextstepistocreatethefixture.Inthiscase,thisisasimpleEditNumberclassthatwewillbetesting:

@Override

protectedvoidsetUp()throwsException{

super.setUp();

editNumber=newEditNumber(mContext);

editNumber.setFocusable(true);

}

ThemockcontextisobtainedfromtheprotectedfieldmContext(http://developer.android.com/reference/android/test/AndroidTestCase.html#mContext),availableintheAndroidTestCaseclass.

AttheendofthesetUpmethod,weseteditNumberasafocusableView,meaningitwillbeabletogainfocus,asitwillbeparticipatinginabunchoftestssimulatingUIsthatmayneedtorequestitsfocusexplicitly.

Next,wetestthattherequiredclear()functionalityisimplementedcorrectlyinthetestClear()method:

@UiThreadTest

publicvoidtestClear(){

Stringvalue="123.45";

editNumber.setText(value);

editNumber.clear();

assertEquals("",editNumber.getText().toString());

}

Runningthetestweverifythatitfails:

junit.framework.ComparisonFailure:expected:<[]>butwas:<[123.45]>

Page 302: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

atcom.blundell.tut.EditNumberTests.testClear(EditNumberTests.java:31)

atjava.lang.reflect.Method.invokeNative(NativeMethod)

atandroid.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)

WeneedtoimplementEditNumber.clear()correctly.

Thisisasimplecase,sojustbyaddingthisimplementationtoEditNumber,wesatisfythetest:

publicvoidclear(){

setText("");

}

Runthetestandproceed.WearegoingtoaddanewmethodtoEditNumber.Here,wealreadyhavegetNumber(),andweareaddingsetNumber()sothatwecanuseitlateron.Nowlet’scompletethetestSetNumber()implementation:

publicvoidtestSetNumber(){

editNumber.setNumber(123.45);

assertEquals("123.45",editNumber.getText().toString());

}

WhichfailsunlessweimplementEditNumber.setNumber(),similartothisimplementation:

privatestaticfinalStringDEFAULT_FORMAT="%."%.2f";";

publicvoidsetNumber(doublenumber){

super.setText(String.format(DEFAULT_FORMAT,number));

}

Weareusingaconstant,DEFAULT_FORMAT,toholdthedesiredformattoconvertthenumbers.ThiscanbelaterconvertedtoapropertythatcouldalsobespecifiedintheXMLlayoutdefinitionofthefield.

ThesamegoesforthetestGetNumber()andgetNumber()pair:

publicvoidtestGetNumber(){

editNumber.setNumber(123.45);

assertEquals(123.45,editNumber.getNumber());

}

AndthegetNumber()methodisasfollows:

publicdoublegetNumber(){

Stringnumber=getText().toString();

if(TextUtils.isEmpty(number)){

return0D;

}

returnDouble.valueOf(number);

}

Thesetestssucceed,sorunyourotherteststoseewhereweareupto;Ididthisonthe

Page 303: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

commandlinerunningthegradlewbuildcATcommand.Thisrunsallofthetestswehavewrittensofar;buttestFahrenheitToCelsiusConversion()isfailing.Wehavealotofwelltestedcode,takeastepback,andreflect.

HereareourAndroidtestresults:

HereareourcoreJavatestresults:

Page 304: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WithtestFahrenheitToCelsiusConversion()ifyoucloselyanalyzethetestcase,canyoucandiscoverwheretheproblemis.

Gotit?

Ourtestmethodisexpectingtheconversiontohappenautomaticallywhenthefocuschanges,aswasspecifiedinourlistofrequirements:“whenonetemperatureisenteredinonefield,theotheroneisautomaticallyupdatedwiththeconversion”.

Remember,wedon’thavebuttonsoranythingelsetoconverttemperaturevalues,sotheconversionistobedoneautomatically,oncethevaluesareentered.

ThisleadsusbacktoourTemperatureConverterActivityclass,andthewayithandlestheconversions.

Page 305: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheTemperatureChangeWatcherclassOnewayofimplementingtherequiredbehaviorofconstantlyupdatingtheothertemperaturevalue,isoncetheoriginalhaschangedisthroughaTextWatcher.Fromthedocumentation,wecanunderstandthataTextWatcherisanobjectofatypethatisattachedtoanEditable;itsmethodswillbecalled,whenthetextischanged(http://developer.android.com/reference/android/text/TextWatcher.html).

Itseemsthatiswhatweneed.

WeimplementthisclassasaninnerclassofTemperatureConverterActivity.Theideabehindthisis,becauseweactdirectlyontheViewsoftheActivity,havingitasaninnerclassshowsthisrelationship,andkeepsitobvious,shouldsomeonethinkofchangingthisActivity’slayout.IfyouimplementtheminimumTextWatcher,yourActivitywilllooklikethis:

publicclassTemperatureConverterActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_temperature_converter);

}

/**

*Changesfieldsvalueswhenthetextchanges;applyingthecorrelated

conversionmethod.

*/

staticclassTemperatureChangedWatcherimplementsTextWatcher{

@Override

publicvoidbeforeTextChanged(CharSequences,intstart,intcount,

intafter){

}

@Override

publicvoidonTextChanged(CharSequences,intstart,intbefore,

intcount){

}

@Override

publicvoidafterTextChanged(Editables){

}

}

}

Andnowthisisourcode,aftersomeadditionstotherecentlycreatedclass:

/**

*Changesfieldsvalueswhenthetextchanges;

*applyingthecorrelatedconversionmethod.

*/

Page 306: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

staticclassTemperatureChangedWatcherimplementsTextWatcher{

privatefinalEditNumbersourceEditNumber;

privatefinalEditNumberdestinationEditNumber;

privatefinalOptionoption;

privateTemperatureChangedWatcher(Optionoption,

EditNumbersource,

EditNumberdestination){

this.option=option;

this.sourceEditNumber=source;

this.destinationEditNumber=destination;

}

staticTemperatureChangedWatchernewCelciusToFehrenheitWatcher(EditNumber

source,EditNumberdestination){

returnnewTemperatureChangedWatcher(Option.C2F,source,destination);

}

staticTemperatureChangedWatchernewFehrenheitToCelciusWatcher(EditNumber

source,EditNumberdestination){

returnnewTemperatureChangedWatcher(Option.F2C,source,destination);

}

@Override

publicvoidonTextChanged(CharSequenceinput,intstart,intbefore,int

count){

if(!destinationEditNumber.hasWindowFocus()

||destinationEditNumber.hasFocus()

||input==null){

return;

}

Stringstr=input.toString();

if("".equals(str)){

destinationEditNumber.setText("");

return;

}

try{

doubletemp=Double.parseDouble(str);

doubleresult=(option==Option.C2F)

?TemperatureConverter.celsiusToFahrenheit(temp)

:TemperatureConverter.fahrenheitToCelsius(temp);

StringresultString=String.format("%.2f",result);

destinationEditNumber.setNumber(result);

destinationEditNumber.setSelection(resultString.length());

}catch(NumberFormatExceptionignore){

//WARNINGthisisgeneratedwhilst

//numbersarebeingentered,

//forexamplejusta'-'

//sowedon''twanttoshowtheerrorjustyet

}catch(Exceptione){

sourceEditNumber.setError("ERROR:"+e.getLocalizedMessage());

}

}

Page 307: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

@Override

publicvoidafterTextChanged(Editableeditable){

//notused

}

@Override

publicvoidbeforeTextChanged(CharSequences,intstart,intcount,int

after){

//notused

}

}

WewillbeusingthesameTemperatureChangeWatcherimplementationforbothfields,CelsiusandFahrenheit;thereforewekeepareferencetothefieldsusedassourceanddestination,aswellastheoperationneededtoupdatetheirvalues.Tospecifythisoperation,weareintroducingenum,whichispureJavaandsocangointothecoremodule:

/**

*C2F:celsiusToFahrenheit

*F2C:fahrenheitToCelsius

*/

publicenumOption{

C2F,F2C

}

Thisoperationisspecifiedinthecreationfactorymethods,andthedestinationandsourceEditNumberareselectedaccordingly.Thiswaywecanusethesamewatcherfordifferentconversions.

ThemethodoftheTextWatcherinterfaceweareinterestedin,isonTextChanged.Thiswillbecalledanytimethetextchanges.Atthebeginning,weavoidpotentialloops,checkingwhohasfocus,andreturningiftheconditionsarenotmet.

Wealsosetthedestinationfieldasanemptystring,ifthesourceisempty.

Finally,wetrytosettheresultingvalueofinvokingthecorrespondingconversionmethodtosetthedestinationfield.Weflagtheerrorasnecessary,avoidingshowingprematureerrors,whentheconversionwasinvokedwithapartiallyenterednumber.

WeneedtosetthelistenerontheinputfieldsinTemperatureConverterActivity.onCreate():

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_temperature_converter);

EditNumbercelsiusEditNumber=

(EditNumber)findViewById(R.id.converter_celsius_input);

EditNumberfahrenheitEditNumber=

(EditNumber)findViewById(R.id.converter_fahrenheit_input);

celsiusEditNumber

.addTextChangedListener(

newCelciusToFehrenheitWatcher(celsiusEditNumber,fahrenheitEditNumber));

Page 308: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

fahrenheitEditNumber

.addTextChangedListener(

newFehrenheitToCelciusWatcher(fahrenheitEditNumber,

celsiusEditNumber));

}

Tobeabletorunthetests,weshouldcompilethem.Tocompile,weneedtoatleastdefinethecelsiusToFahrenheit()method,whichisnotyetdefined.

Page 309: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MoreTemperatureConvertertestsWeneedtoimplementcelsiusToFahrenheit,andasusualwestartfromthetest.

ThisisfairlyequivalenttotheotherconversionmethodfahrenheitToCelsius,andwecanusetheinfrastructurewedevisedwhilecreatingthistest:

@Test

publicvoidtestCelsiusToFahrenheit(){

for(doubleknownCelsius:conversionTable.keySet()){

doubleknownFahrenheit=conversionTable.get(knownCelsius);

doubleresultFahrenheit=

TemperatureConverter.celsiusToFahrenheit(knownCelsius);

doubledelta=Math.abs(resultFahrenheit-knownFahrenheit);

Stringmsg=knownCelsius+"C->"+knownFahrenheit+"F"

+"butis"+resultFahrenheit;

assertTrue(msg,delta<0.0001);

}

}

Weusetheconversiontabletoexercisethemethodthroughdifferentconversions,andweverifythattheerrorislessthanapredefineddelta.

Then,thecorrespondentconversionimplementationintheTemperatureConverterclassisasfollows:

staticfinaldoubleABSOLUTE_ZERO_C=-273.15d;

publicstaticdoublecelsiusToFahrenheit(doublecelsius){

if(celsius<ABSOLUTE_ZERO_C){

Stringmsg=String.format(

ERROR_MESSAGE_BELOW_ZERO_FMT,celsius,'C');

thrownewInvalidTemperatureException(msg);

}

return(celsius*1.8d+32);

}

Now,allthetestsarepassingbutwearestillnottestingallthecommonconditions.WhatImeanbythisisthatwehavebeencheckingthehappypathsofar.Youshouldcheckwhethererrorsandexceptionsarecorrectlygenerated,besidesallthenormalcaseswecreatedsofar.

Createthistesttocheckthecorrectgenerationofexceptions,whenatemperaturebelowabsolutezeroisusedinaconversion:

@Test(expected=InvalidTemperatureException.class)

publicvoidtestExceptionForLessThanAbsoluteZeroF(){

TemperatureConverter.fahrenheitToCelsius(ABSOLUTE_ZERO_F-1);

}

Inthistest,wedecrementtheabsolutezerotemperature,toobtainanevensmallervalue,andthenweattempttheconversion.Wewrotethistestinourcoremodule,andtherefore

Page 310: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

usedJUnit4,whichallowsustouseannotationstoassertthatweexpectanexceptiontobethrown.IfyouwantedtodothesamethinginJUnit3,youwouldhavetouseatrycatchblock,andfailthetestifthecodedidnotenterthecatchblock:

@Test(expected=InvalidTemperatureException.class)

publicvoidtestExceptionForLessThanAbsoluteZeroC(){

TemperatureConverter.celsiusToFahrenheit(ABSOLUTE_ZERO_C-1);

}

Inasimilarmanner,wetestfortheexceptionbeingthrown,whentheattemptedconversioninvolvesatemperatureinCelsius,thatislowerthantheabsolutezero.

Page 311: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TheInputFiltertestsAnothererrorrequirementcouldbe:Wewanttofiltertheinputthatisreceivedbytheconversionutility,sonogarbagereachesthispoint.

TheEditNumberclassalreadyfiltersvalidinput,andgeneratesexceptionsotherwise.WecanverifythisconditionbycreatinganewtestinTemperatureConverterActivityTests.Wechoosethisclassbecausewearesendingkeystotheentryfields,justasarealuserwoulddo:

publicvoidtestInputFilter()throwsThrowable{

runTestOnUiThread(newRunnable(){

@Override

publicvoidrun(){

celsiusInput.requestFocus();

}

});

getInstrumentation().waitForIdleSync();

sendKeys("MINUS1PERIOD2PERIOD3PERIOD4");

doublenumber=celsiusInput.getNumber();

Stringmsg="-1.2.3.4shouldbefilteredto-1.234"

+"butis"+number;

assertEquals(msg,-1.234d,number);

}

ThistestrequeststhefocusontotheCelsiusfieldusingthepatternreviewedpreviously.ThisallowsustorunpartsofatestintheUIthread,andsendkeyinputtotheview.Thekeyssentareaninvalidsequencecontainingmorethanoneperiod,whichisnotacceptedforawell-formeddecimalnumber.Itisexpectedthatwhenthefilterisinplace,thissequencewillbefiltered,andonlythevalidcharactersreachthefield.AssertingthatthevaluereturnedbycelsiusInput.getNumber(),iswhatweexpectafterfiltering.

Toimplementthisfilter,weneedtoaddInputFiltertoEditNumber.Becausethisshouldbeaddedtoalloftheconstructors,wecreateanadditionalinit()method,whichweinvokefromeach.ToachieveourgoalweuseaninstanceofDigitsKeyListener,acceptingdigits,signs,anddecimalpointsasfollows:

publicEditNumber(Contextcontext){

super(context);

init();

}

publicEditNumber(Contextcontext,AttributeSetattrs){

super(context,attrs);

init();

}

publicEditNumber(Contextcontext,AttributeSetattrs,intdefStyle){

super(context,attrs,defStyle);

init();

}

Page 312: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

privatevoidinit(){

//DigistKeyListener.getInstance(true,true)

//returnsaninstancethatacceptsdigits,signanddecimalpoint

InputFilter[]filters=

newInputFilter[]{DigitsKeyListener.getInstance(true,true)};

setFilters(filters);

}

Thisinitmethodisinvokedfromeachconstructor,sothatifthisviewisusedprogrammaticallyorfromXML,westillhaveourfilter.

Runningthetestsagain,wecanverifythatallhavepassed,andnoweverythingisgreenagain.

Page 313: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 314: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ViewingourfinalapplicationWelldone!Wenowhaveourfinalapplicationthatsatisfiesalltherequirements.

Inthefollowingscreenshotweareshowingoneoftheserequirements,whichisthedetectionofanattempttoconvertatemperaturebelowtheabsolutezerotemperatureinCelsius(-1000.00C):

TheUIrespectstheguidelinesprovided;thetemperaturescanbeconvertedbyenteringtheminthecorrespondingunitfield.

Torecap,thisisthelistofrequirementsthatwehaveimplemented:

TheapplicationconvertstemperaturesfromCelsiustoFahrenheit,andviceversaTheuserinterfacepresentstwofieldstoenterthetemperatures,oneforCelsiusandtheotherforFahrenheitWhenonetemperatureisenteredinonefield,theotheroneisautomaticallyupdatedwiththeconversionIfthereareerrors,theyshouldbedisplayedtotheuser,possiblyusingthesamefieldsSomespaceintheuserinterfaceshouldbereservedfortheon-screenkeyboard,toeasetheapplicationoperationwhenseveralconversionsareenteredEntryfieldsshouldstartemptyValuesenteredaredecimalvalueswithtwodigitsafterthepointDigitsarerightaligned

Whatismoreimportantisthatwecannowbecertainthattheapplicationnotonlysatisfies

Page 315: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

therequirements,butalsohasnoevidentproblemsorbugs.Wetookeverystepbyanalyzingthetestresults,andfixingtheproblemsattheirfirstappearance.Thiswillensurethatanyindividualbug,oncediscovered,testedandfixed,willnotresurfaceagain.

Page 316: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 317: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryWepresentedTest-drivenDevelopmentintroducingitsconcepts,andapplyingthemstep-by-stepinapotentialreal-lifeproblem.

Westartedwithaconciselistofrequirements,describingthetemperatureconverterapplication.

Weimplementedeverytestfollowedbythecodethatsatisfiesit.Inthismanner,weimplementedtheapplicationbehavioraswellasitspresentation,conductingteststoverifythattheUIwedesignedfollowsthespecifications.

Havingthetestsinplace,leadustoanalyzethedifferentpossibilitieswehaveinrunningthem.Evolvingfromthepreviouschapter,nowourcontinuousintegrationmachinecanruntheteststoguaranteeanychangesfromtheteamwillstillresultinawell-testedapplication.

ThenextchapterintroducesBehavior-drivenDevelopment,andcontinuesouraimforbug-freewell-testedcode,thistimewithafocusuponbehaviorandagreement,onwhatarequirementmeansthroughouttheteam.

Page 318: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 319: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter7.Behavior-drivenDevelopmentBehavior-drivenDevelopment(BDD)canbeunderstoodastheevolutionandconfluenceofTest-drivenDevelopment(TDD)andacceptancetesting.Bothtechniqueswerediscussedinpreviouschapters,soyoumaywanttolookbackatChapter1,GettingStartedwithTesting,andChapter6,PracticingTest-drivenDevelopment,beforeproceeding.

Behavior-drivenDevelopmentintroducessomenewconcepts,suchastheuseofacommonvocabularytodescribethetests,andtheinclusionofbusinessparticipantsinthesoftwaredevelopmentproject,suchasproductownersorbusinessanalysts.

WehavevisitedTest-drivenDevelopmentbefore,andwefocusedonconvertinglow-levelrequirementsintoteststhatcoulddriveourdevelopmentprocess.Behavior-drivenDevelopmentforcesustoconcentrateonhigherlevelrequirements,andbyusingaspecificvocabulary,wecanexpresstheserequirementsinawaythatcanbefurtheranalyzedorevaluated.SomepeoplebelieveBDDisonlythephilosophyofTDDdoneright.

Wewillexploretheseconceptsthroughexamples,sothatyoucandrawyourownconclusions.

Page 320: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Given,When,andThenGiven/When/Thenwordsarethecommonvocabularythatspansthedividebetweenbusinessandtechnology,andasdescribedathttp://behaviour-driven.org,theycanalsobereferredtoastheubiquitouslanguageofBehavior-drivenDevelopment.Theframeworkisbasedonthefollowingthreecoreprinciplesthatwereproducehere,verbatim:

BusinessandtechnologyshouldrefertothesamesysteminthesamewayAnysystemshouldhaveanidentified,verifiablevaluetothebusinessUp-frontanalysis,design,andplanning,allhaveadiminishingreturn

Behavior-drivenDevelopmentreliesontheuseofthisspecificvocabulary.Additionally,theformatinwhichrequirementsareexpressedispredetermined,allowingtoolstointerpretandexecutethem:

Given:Thisistodescribetheinitialstatebeforeanexternalstimuliisreceived.When:Thisistodescribethekeyactiontheuserperforms.Then:Thisistoanalyzetheresultsoftheactions.Tobeobservable,theactionsperformedshouldhavesomekindofoutcome.

Page 321: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 322: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

FitNesseFitNesseisasoftwaredevelopmentcollaborationtoolthatcanbeusedtomanageBDDscenarios.StrictlyspeakingFitNesseisasetoftools,describedasfollows:

Asasoftwaretestingtool,FitNesseisalightweight,opensourceframeworkthatallowsteamstocollaborateItisalsoaWikiwhereyoucaneasilycreate,editpages,andshareinformationAwebserver,soitdoesn’trequireadditionalconfigurationoradministrativeprivilegestosetup,orconfigure

DownloadtheFitNessedistributionfromhttp://www.fitnesse.org.ThedistributionisaJARfilethatinstallsitselfonfirstrun.Throughouttheseexamples,weusedFitNessestandalonerelease20140901butnewerversionsshouldalsowork.

Page 323: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningFitNessefromthecommandlineBydefault,whenFitNesseruns,itlistensonport80,sotorununprivileged,youshouldchangetheportonthecommandline.Inthisexample,weuse8900:

$java-jarfitnesse.jar-p8900

Thisistheoutputobtainedwhenwerunthecommand:

BootstrappingFitNesse,thefullyintegratedstandalonewikiandacceptance

testingframework.

rootpage:fitnesse.wiki.fs.FileSystemPageat./FitNesseRoot#latest

logger:none

authenticator:fitnesse.authentication.PromiscuousAuthenticator

pagefactory:fitnesse.html.template.PageFactory

pagetheme:fitnesse_straight

StartingFitNesseonport:8900

Oncerunning,youcandirectyourbrowsertothelocalFitNesseserverhomepage(http://localhost:8900/FrontPage),andyouwillbepresentedwiththiscontent:

Page 324: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingaTemperatureConverterTestssubwikiOnceFitNesseisupandrunning,wecanstartbycreatingasubwikitoorganizeourtests.Youmayalreadybefamiliarwiththewikiconcept.Ifnot,wikiisawebsitethatallowspageeditingandcreationbyitsusers.Thiseditingprocessisdonefromwithinthebrowser,andusesamarkuplanguagethatgreatlysimplifiestheprocess.

NoteYoucanfindoutmoreaboutwikisinwhatcouldperhapsbethemostfamouswikiathttp://en.wikipedia.org/wiki/Wiki.

Thoughthissubwikiorganizationisnotmandatory,itishighlyrecommended,especiallyifyouplantouseFitNesseforacceptancetestingonmultipleprojects.

Oneofthemostsimplifiedprocessesishyperlinkcreation,whichisdoneonlybyusingCamelCaseorWikiWords;thatisawordthatstartswithacapitalletterandhasatleastoneormorecapitalletterinit.ThisWikiWordwillbeconvertedintoahyperlinktoapage,withthatname.

TocreatetheTemperatureConverterTestssubwiki,wesimplypresstheEditbuttontotherightoftheFitNesselogo,toeditthehomepage,addingthefollowing:

|'''MyTests'''|

|TemperatureConverterTests|''TemperatureConverterTests''|

Thisaddsanewtabletothepagebyusingthe“|”markupasthefirstcharacterandtodelimitthecolumns.

Wealsoaddacolumnwithadescriptivecommentaboutthetests.Thiscommentisturnedintoitalicsbysurroundingitwithtwosinglequotes(”).Thistextwillcreateawikilinknamed,TemperatureConverterTests.

PressSave,andthepagewillbemodified.

Oncethepageisdisplayed,wecanverifythatTemperatureConverterTestsisnowfollowedbya[?](questionmark)becausethepagehasnotbeencreatedyet,andwillbecreatedwhenweclickonit.Clickonitnow,thisputsusstraightintoeditmodeofthenewpage.Wecanaddsomecommentstoclearlyidentifythisnewlycreatedfrontpageofthesubwiki:

!contents-R2-g-p-f-h

Thisisthe!-TemperatureConverterTestsSubWiki-!.

Here,thetextTemperatureConverterTestsSubWikiisescapedusing!-and-!topreventitfrombeingconvertedtoanotherpagelink.

PressSaveagain.

AddingchildpagestothesubwikiNow,weaddanewchildpagebyusingthe[Add]linkthatappearsnexttothepagetitle.

Page 325: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Therearedifferentoptionsforcreatingthechildpage,andwecanselect:

Static:ThisisanormalWikipageSuite:ThisisapagecontainingothertestscomposingasuiteTest:Thisisapagethatcontainstests

WewillselecttoaddasuitepageandcallitTemperatureConverterTestSuiteasshowninthefollowingscreenshot:

AfterpressingSave,thispageiscreatedandhasbeenautomaticallyaddedasalinktotheTemperatureConverterTestssubwiki.

Let’sfollowthisnewlycreatedlinktoreachthetestsuitepage.

Onceyou’rehere,addanotherchildusing[Add]|[TestPage].Thisaddsatestpage,andwewillnameitTemperatureConverterCelsiusToFahrenheitFixture,asthiswillcontainourfixture.Thenaminghereisjustaconventiontoorganizeourwiki.

ClickonSavetofinishtheoperation.

AddingtheacceptancetestfixtureUpuntilnow,wewereonlycreatingwikipages.Nothingexcitingaboutthat!Now,wewillbeaddingouracceptancetestfixturedirectlytothepage.Besureyouhavenavigatedtothenewlyaddedpage,TemperatureConverterCelsiusToFahrenheitFixture,clickonEdit,andreplace<testpage>withthefollowing:

!contents

!|TemperatureConverterCelsiusToFahrenheitFixture|

|celsius|fahrenheit?|

|0.0|~=32|

|100.0|212.0|

|-1.0|30.2|

|-100.0|-148.0|

|32.0|89.6|

Page 326: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

|-40.0|-40.0|

|-273.0|~=-459.4|

|-273|~=-459.4|

|-273|~=-459|

|-273|~=-459.40000000000003|

|-273|-459.40000000000003|

|-273|-459.41<_<-459.40|

|-274.0|Invalidtemperature:-274.00Cbelowabsolutezero|

Thistabledefinesseveralitemsforourtestfeature:

TemperatureConverterCelsiusToFahrenheitFixture:Thisisthetabletitleandthetestfixturename.celsius:Thisisthecolumnnameforthevalueweareprovidingasinputtothetest.fahrenheit?:Thisisthecolumnnameforthevalueexpectedastheresultoftheconversion.Thequestionmarkindicatesthatthisisaresultvalue.~=:Thisindicatesthattheresultisapproximatelythisvalue.<_<:Thisindicatesthattheexpectedvalueiswithinthisrange.Invalidtemperature:-274.00Cbelowabsolutezeroisthevalueexpectedbythefailedconversion.

SavethiscontentbyclickingonSave.

AddingthesupportingtestclassesIfwepresstheTestbutton,whichisbelowtheFitNesselogo(seethefollowingscreenshotfordetails),wewillreceiveanerror.Insomewaythisisexpectedbecausewehaven’tcreatedthesupportingtestfixtureyet.ThetestfixturewillbeaverysimpleclassthatinvokestheTemperatureConverterclassmethods.

FitNessesupportsthefollowingtwodifferenttestsystems:

fit:ThisistheolderofthetwomethodsandusesHTML,parsedjustpriortothefixturebeingcalledslim:Thisisnewer;allthetableprocessingisdoneinsideFitNessewithinslimrunners

Furtherinformationaboutthesetestsystemscanbefoundathttp://fitnesse.org/FitNesse.UserGuide.WritingAcceptanceTests.TestSystems.

Inthisexample,weuseslim,bysettingthevariableTEST_SYSTEMwithinthesamepageasfollows:

!defineTEST_SYSTEM{slim}

Now,wearegoingtocreatetheslimtestfixture.RememberthetextfixtureisasimpleclassthatallowsustorunouralreadywrittentemperatureconversioncodefromtheFitNessetestsuite.Wecreateanewpackage,namedcom.blundell.tut.fitnesse.fixture,insideofourexistingprojectTemperatureConverterandinsidethecoremodule.Wewillbecreatingthefixtureinsidethispackage.

Next,wehavetocreatetheTemperatureConverterCelsiusToFahrenheitFixtureclass,

Page 327: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

whichwedefinedinouracceptancetesttable:

publicclassTemperatureConverterCelsiusToFahrenheitFixture{

privatedoublecelsius;

publicvoidsetCelsius(doublecelsius){

this.celsius=celsius;

}

publicStringfahrenheit()throwsException{

try{

doublefahrenheit=TemperatureConverter

.celsiusToFahrenheit(celsius);

returnString.valueOf(fahrenheit);

}catch(RuntimeExceptione){

returne.getLocalizedMessage();

}

}

}

Asareminderitshouldlooksomethinglikethiswhendone:

Thisfixtureshoulddelegatetoourrealcodeandnotdoanythingbyitself.WedecidedtoreturnStringfromfahrenheit(),sowecanreturntheExceptionmessageinthesamemethod.

Atthispoint,runthecoremoduleteststoensureyouhavenotbrokenanything(andtocompilethenewlycreatedclassforlater).

OntheFitNessetestpage,weshouldalsodefinethepackagethetestresidesin.ThisallowsthetestswritteninFitNessetofindthetestfixturewritteninourAndroidproject.Inthesamepagewearestillediting,add:

|import|

|com.blundell.tut.fitnesse.fixture|

Now,weaddourAndroidprojectclassfilestothepathofourFitNessetests.ThisallowsFitNessetouseournewlywrittentestfixtureandourTemperatureConverter;thecodeundertest:

!path

/Users/blundell/AndroidApplicationTestingGuide/core/build/classes/test

!path

Page 328: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

/Users/blundell/AndroidApplicationTestingGuide/core/build/classes/main

NoteThisshouldbeadaptedtoyoursystempaths.Themainpointhereisthepathafter/core/.Thisispointingtowherethecompiled*.classfilesareforyourapplicationundertest.Note,thatweneedtoaddthetestsourcesandtheprojectsourcesseparately.

Afterfinishingthesesteps,wecanclickontheTestbuttontorunthetests,andthefollowingscreenshotwillreflecttheresults:

Wecaneasilyidentifyeverytestthatsucceededbytheirgreencolor,andthefailedonesbytheirredcolor.Inthisexample,wedon’thaveanyfailure,soeverythingisgreen.Notice,italsoshowstheclasspathandTEST_SYSTEMvariableswedeclared.

Page 329: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

FitNessehasanotherusefulfeature,TestHistory.Allthetestrunsandaspecificnumberofresultsaresavedforaperiodoftime,sothatyoucanreviewtheresultslateronandcomparethem,andthus,analyzetheevolutionofyourchanges.

ThisfeatureisaccessedbyclickingTestHistorylocatedatthebottomofthelist,underTools,onthetopmenu.

Inthefollowingscreenshot,wecanseetheresultsforthelast3testruns,where2failedand1succeeded.Alsobyclickingonthe+(plus)or-(minus)signs,youcanexpandorcollapsetheviewtoshoworhidedetailedinformationaboutthetestrun:

Page 330: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 331: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GivWenZenGivWenZenisaframeworkthatbuildsuponFitNesseandSlimtoallowtheusertoexploittheBehavior-drivenDevelopmenttechniqueofexpression,usingtheGiven-When-Thenvocabularytodescribetests.ThesetestdescriptionsarealsocreatedusingtheFitNessewikifacility,ofexpressingthetestsasplaintextcontainedintablesinawikipage.

Theideaissimpleandstraightforward,andfollowsupwithwhatwehavebeendoingwithFitNesse,butthistimeinsteadofwritingacceptancetestsgivingatableofvalues,wewillusethethreeBehavior-drivenDevelopmentmagicwords,Given-When-Then,todescribeourscenarios.

Firstly,let’sinstallFitNessewithGivWenZen.Downloadthefulldistributionfromitsdownloadlistpageathttp://goo.gl/o3Hlpo.Onceunzipped,theGivWenZenJARstartsupexactlythesamewayasFitNessedid(becauseit’sjustamodificationontop):

$java-jar/lib/fitnesse.jar-p8900

Furtherreading,comprehensiveinstructionsandexamplescanbefoundonthewikiathttps://github.com/weswilliams/GivWenZen/wiki.WeusedGivWenZen1.0.3intheseexamples,butnewerversionsshouldworkaswell.

TheGivWenZenfulldistributionincludesallthedependenciesneeded,includingFitNesse,soifyouhaveFitNesserunningfrompreviousexamplesitisbettertostopit,asyoumustuseadifferentJARforGivWenZen.

Uponstartup,pointyourbrowsertothehomepageandyouwillfindafamiliarFitNessefrontpage,orifyouhaveconfiguredtheportlikewedidpreviously,checkoutsometestsathttp://localhost:8900/GivWenZenTests.Youcantakesometimetoexploretheexamplesincluded.

Page 332: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingthetestscenarioLet’screateasimplescenarioforourtemperatureconverter,sowecanunderstandGiven-When-Thenabitbetter.

AsaplainEnglishsentence,ourscenariowouldbe:

GivenI’musingtheTemperatureConverter,WhenIenter100intotheCelsiusfield,ThenIobtain212intheFahrenheitfield.

ThevalueisdirectlytranslatedintoaGivWenZenscenariobyaddingthistoawikipage:

-|script|

|given|I'musingthe!-TemperatureConverter-!|

|when|Ienter100intotheCelsiusfield|

|then|Iobtain212intheFahrenheitfield|

Thetranslationisstraightforward.Thetabletitlemustbescript,andinthiscaseitisprecededbyadash(-)tohideit.TheneachoftheGiven-When-Thenscenariosisplacedinacolumn,andthepredicateintheothercolumn.

Beforerunningthisscript,whenthewholepageisexecuted,weneedtoinitializeGivWenZenbyrunninganotherscript.Youdothisbyaddingittothetopofthewikipage:

|import|

|org.givwenzen|

-|script|

|start|givwenzenforslim|

Wealsoneedtoinitializetheclasspathandaddthecorrespondingimportsforallscripts.Usually,thisisdoneinoneoftheSetUppages,whichareexecutedbeforerunningeverytestscript(likethesetUp()methodinaJUnittest),butforthesakeofsimplicity,weareaddingtheinitializationtothissamepage:

!defineTEST_SYSTEM{slim}

!path./target/classes

!path./target/examples

!path./lib/clover-2.6.1.jar

!path./lib/commons-logging.jar

!path./lib/commons-vfs-1.0.jar

!path./lib/dom4j-1.6.1.jar

!path./lib/fitnesse.jar

!path./lib/guava-18.0.jar

!path./lib/javassist.jar

!path./lib/log4j-1.2.9.jar

!path./lib/slf4j-simple-1.5.6.jar

!path./lib/slf4j-api-1.5.6.jar

!path./givwenzen-20150106.jar

!path

/Users/blundell/AndroidApplicationTestingGuide/core/build/classes/test

!path

/Users/blundell/AndroidApplicationTestingGuide/core/build/classes/main

YouwillneedtochangethelasttwopathvariablestomatchyourTemperatureConverter

Page 333: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

project;you’llseewhyyouneedtheselater.

IfyourunthetestsatthispointbyclickingtheTestbutton,youwillreceivethefollowingmessage:

__EXCEPTION__:org.givwenzen.DomainStepNotFoundException:

Thesecondcolumninthetable,forourtestoutline,holdsthedomainsteps,hence,theexceptionDomainStepNotFound.Youneedastepclasswithanannotatedmethodmatchingthispattern:“I’musingtheTemperatureConverter”.

Typicalcausesofthiserrorareasfollows:

StepClassismissing:ThisisourerrorStepClassismissingthe@DomainStepsannotationStepMethodismissingthe@DomainStepannotationTheStepMethodannotationhasaregularexpressionthatdoesnotmatchthecurrentteststepyouhavewritten

Anexamplestepclasscouldbe:

@DomainSteps

publicclassStepClass{

@DomainStep("I'musingtheTemperatureConverter")

publicvoiddomainStep(){

//TODOimplementstepbyinvokingyourowncode

}

}

Thestepclassshouldbeplacedinthepackageorsubpackageofbdd.steps,oryoucouldalternativelydefineyourowncustompackage.Thispackageisgoingtoliveinsidethe/core/test/moduleofourapplication.Ifyounoticed,abovethesetUppage,weaddedourapplicationonthepath,sothisDomainStepcanbefoundafterwebuildtheproject.

Inordertousethe@DomainStep(s)annotationinourproject,weneedtheGivWenZenJARonourprojecttestpath.Thiscanbedonebycopyingthegivwenzen.jarfileinto/core/libs,orevenbetterwithGradlebyaddingitasaremotedependencytobuild.gradle:

testCompile'com.github.bernerbits:givwenzen:1.0.6.1'

TipYou’llnoticethatthistestCompiledependencyisn’ttheofficialGivWenZenreleasebutsomeonehasforked(copied)thecode,anduploadedit.Thisdoesn’tmattertousfornowbecauseweareonlyusingthetwoannotationclasses(whichIknowareidenticalinthisversion),butit’sworthkeepinginmindandrevertingtotheoriginalGivWenZenlibraryifitiseverreleasedasaremotedependency.

Followingthesmalloutlineexample,inourparticularcasetheimplementationofStepClasswillbe:

packagebdd.steps.tc;

Page 334: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

importcom.blundell.tut.TemperatureConverter;

importorg.givwenzen.annotations.DomainStep;

importorg.givwenzen.annotations.DomainSteps;

@DomainSteps

publicclassTemperatureConverterSteps{

privatestaticfinalStringCELSIUS="Celsius";

privatestaticfinalStringFAHRENHEIT="Fahrenheit";

privatestaticfinalStringUNIT_NAME

="("+CELSIUS+"|"+FAHRENHEIT+")";

privatestaticfinalStringANY_TEMPERATURE

="([-+]?\\d+(?:\\.\\d+)?)";

privatedoubleinputTemperature=Double.NaN;

@DomainStep("I(?:a|')musingtheTemperatureConverter")

publicvoidcreateTemperatureConverter(){

//donothing

}

@DomainStep("Ienter"+ANY_TEMPERATURE

+"intothe"+UNIT_NAME+"field")

publicvoidsetField(doubleinputTemperature,StringunitName){

this.inputTemperature=inputTemperature;

}

@DomainStep("Iobtain"+ANY_TEMPERATURE

+"inthe"+UNIT_NAME+"field")

publicbooleanverifyConversion(doubleexpectedTemperature,String

unitName){

doubleoutputTemperature=convertInputInto(unitName);

returnMath.abs(outputTemperature-expectedTemperature)<0.01D;

}

privatedoubleconvertInputInto(StringunitName){

doubleconvertedInputTemperature;

if(CELSIUS.equals(unitName)){

convertedInputTemperature=getCelsius();

}elseif(FAHRENHEIT.equals(unitName)){

convertedInputTemperature=getFahrenheit();

}else{

thrownewRuntimeException("Unknownconversionunit"+

unitName);

}

returnconvertedInputTemperature;

}

privatedoublegetCelsius(){

returnTemperatureConverter.fahrenheitToCelsius(inputTemperature);

}

privatedoublegetFahrenheit(){

returnTemperatureConverter.celsiusToFahrenheit(inputTemperature);

Page 335: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

}

}

Inthisexample,weareusingasubpackageofbdd.stepsbecause,bydefault,thisisthepackagehierarchyGivWenZensearchesforstep’simplementations.Otherwise,extraconfigurationisneeded.

Classesimplementingstepsshouldbeannotatedby@DomainSteps,andeachofthestep’smethodsannotatedby@DomainStep.EachstepmethodannotationreceivesaStringregularexpressionasaparameter.ThisregularexpressionisusedbyGivWenZentomatchthesteps.

Forexample,inourscenario,wehavedefinedthisstep:

Ienter100intotheCelsiusfield

Ourannotationisasfollows:

@DomainStep("Ienter"+ANY_TEMPERATURE

+"intothe"+UNIT_NAME+"field")

Thiswillmatch,andtheregularexpressiongroupvaluesdefinedbyANY_TEMPERATUREandUNIT_NAMEwillbeobtainedandprovidedtothemethodasitsargument’svalueandunitName:

publicvoidsetField(doubleinputTemperature,StringunitName)

RecallthatinapreviouschapterIrecommendedreviewingregularexpressionsbecausetheycouldbeuseful.Wellthisisprobablyoneoftheseplaceswheretheyareextremelyuseful.ItallowsforaflexibleuseoftheEnglishlanguage.HereI(?:a|'m)wasusedtoallowIamandI’m.InANY_TEMPERATURE,wearematchingeverypossibletemperaturevaluewiththeoptionalsignanddecimalpoint.ConsequentlyUNIT_NAMEmatchestheunitname;thatis,CelsiusorFahrenheit.

Theseregularexpressionsareusedintheconstructionofthe@DomainStepannotationparameters.Groupsdelimitedby()parenthesisintheseregularexpressionsareconvertedintomethodparameters.ThisishowsetField()obtainsitsparameters.

ThenwehaveaverifyConversion()methodthatreturnstrueorfalsedependingonwhethertheactualconversionmatchestheexpectedone,withinadifferenceoftwodecimalplaces.

Finally,wehavesomemethodsthatactuallyinvoketheconversionmethodsintheTemperatureConverterclass.

Onrunningthetestsonceagain,allthetestspass.Wecanconfirmthisbyanalyzingtheoutputmessage:

Assertions:1right,0wrong,0ignored,0exceptions.

Weshouldnotonlycreatescenariosfornormalsituations,butcoverexceptionalconditionsaswell.Say,inplaintext,ourscenarioissomethinglikethis:

Note

Page 336: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GivenI’musingtheTemperatureConverter,whenIenter-274intotheCelsiusfield,thenIobtainanInvalidtemperature:-274.00Cbelowabsolutezeroexception.

ItcanbetranslatedintoaGivWenZentablelikethefollowing:

-|script|

|given|Iamusingthe!-TemperatureConverter-!|

|when|Ienter-274intotheCelsiusfield|

|then|Iobtain'Invalidtemperature:-274.00Cbelowabsolutezero'

exception|

Byaddingasinglesupportingstepmethod,wewillbeabletorunit.Thestepmethodcanbeimplementedlikethis:

@DomainStep("Iobtain'(Invalidtemperature:"+ANY_TEMPERATURE+"

C|Fbelowabsolutezero)'exception")

publicbooleanverifyException(Stringmessage,Stringvalue,String

unit){

try{

if("C".equals(unit)){

getFahrenheit();

}else{

getCelsius();

}

}catch(RuntimeExceptionex){

returnex.getMessage().contains(message);

}

returnfalse;

}

Thismethodobtainstheexceptionmessage,temperaturevalue,andunitfromtheregularexpression.Thenthisiscomparedagainsttheactualexceptionmessagetoverifythatitmatches.

NoteDon’tforgetwhenyouaddJavacodetoyourStepClassannotationyouwillneedtocompiletheclassagainsothatFitNessecanusethenewcode.OnewaytodothisisjusttorunyourJavatestsfromtheIDE,forcingarecompile.

Additionally,wecancreateotherscenariosthat,inthissituation,willbesupportedbytheexistingstep’smethods.Thesescenarioscouldbe:

-|script|

|given|I'musingthe!-TemperatureConverter-!|

|when|Ienter-100intotheCelsiusfield|

|then|Iobtain-148intheFahrenheitfield|

-|script|

|given|I'musingthe!-TemperatureConverter-!|

|when|Ienter-100intotheFahrenheitfield|

|then|Iobtain-73.33intheCelsiusfield|

-|script|

|given|I'musingthe!-TemperatureConverter-!|

Page 337: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

|when|Ienter-460intotheFahrenheitfield|

|then|Iobtain'Invalidtemperature:-460.00Fbelowabsolutezero'

exception|

BecauseGivWenZenisbasedonFitNesse,wearefreetocombinebothapproachesandincludethetestsfromourprevioussession,inthesamesuite.Doingso,wecanruntheentiresuitefromthesuitepage,obtainingtheoverallresultsasfollows:

Page 338: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 339: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryInthischapter,wediscoveredBehavior-drivenDevelopmentasanevolutionofTest-drivenDevelopment,whichweexaminedinpreviouschapters.

WediscussedthedrivingforcesbehindBehavior-drivenDevelopment.Weanalyzedtheconceptsservingasthefoundations,exploredtheGiven-When-Thenvocabularyidea,andintroducedFitNesseandSlimashelpfultoolsindeployingtests.

WepresentedGivWenZen,atoolbasedonFitNessethatgivesustheabilitytocreatenear-English,prose-stylescenarios,andtestthem.

WeintroducedthesetechniquesandtoolstooursampleAndroidproject.However,wearestilllimitedtotestsubjectsthataretestableundertheJVM,avoidingtheuseofAndroid-specificclassesandtheuserinterface.WewillbeexploringsomealternativestoovercomethislimitationinChapter9,AlternativeTestingTactics.

Thenextchapterdealswithadifferentaspectoftesting,concentratingonperformanceandprofiling,whichisanaturalsteptofollowafterwehaveourapplicationbehavingcorrectly,andaccordingtoourtestspecifications.

Page 340: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 341: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter8.TestingandProfilingPerformanceInthepreviouschapters,westudiedanddevelopedtestsforourAndroidapplication.Thosetestsletusevaluatecomplianceagainstaspecificationandallowedustodeterminewhetherthesoftwarewasbehavingcorrectlyornotaccordingtotheserulesbytakingabinaryverdict,whetheritcompliedgreenornot.Ifalltestcasespass,itmeansoursoftwareisbehavingasexpected.Ifoneofthetestcasesfails,thesoftwareneedstobefixed.

Inmanyothercases,mainlyafterwehaveverifiedthatthesoftwareconformstoallthesespecifications,wewanttomoveforwardandknowhoworinwhatmannerthecriteriaaresatisfied.Atthesametime,wewouldwanttoknowhowthesystemperformsunderdifferentsituationstoanalyzeotherattributessuchasusability,speed,responsetime,andreliability.

AccordingtotheAndroiddeveloperguide(http://developer.android.com/),thesearethebestpracticeswhenitcomestodesigningourapplication:

DesigningforperformanceDesigningforresponsivenessDesigningforseamlessness

It’sextremelyimportanttofollowthesebestpracticesandtothinkaboutperformanceandresponsivenessfromtheverybeginningofthedesign.SinceourapplicationwillrunonAndroiddeviceswithlimitedcomputerpower,identifyingthetargetsforoptimizationonceourapplicationisbuilt,atleastpartially,andthenapplyingtheperformancetesting(whichwewillbediscussingsoon)canbringusbiggergains.

DonaldKnuthpopularizedthisyearsago:

“Prematureoptimizationistherootofallevil”.

Optimizations,whicharebasedonguesses,intuition,andevensuperstition,ofteninterferewiththedesignovershort-termperiods,andwithreadabilityandmaintainabilityoverlong-termperiods.Onthecontrary,micro-optimizationsarebasedonidentifyingthebottlenecksorhotspotsthatrequireoptimization,applyingthechanges,andthenbenchmarkingagaintoevaluatetheimprovementsoftheoptimization.So,thepointweareconcentratingonhereismeasuringtheexistingperformanceandtheoptimizationalternatives.

Thischapterwillintroduceaseriesofconceptsrelatedtobenchmarkingandprofiling,asfollows:

TraditionalloggingstatementmethodsCreatingAndroidperformancetestsUsingprofilingtools

Page 342: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MicrobenchmarksusingCaliper

Page 343: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

YeOldeLoggemethodSometimes,thisistoosimplisticforreal-lifescenariosbutI’mnotgoingtosaythatitcouldnothelpinsomecases,mainlybecauseitsimplementationtakesminutesandyouonlyneedthelogcattextoutputtoanalyzethecase.Thiscomesinhandyduringsituationswhereyouwanttoautomateproceduresorapplycontinuousintegration,asdescribedinpreviouschapters.

Thismethodconsistsoftimingamethod(orapartofit),surroundingitbytwotimemeasures,andloggingthedifferenceattheend:

privatestaticfinalbooleanBENCHMARK_TEMPERATURE_CONVERSION=true;

@Override

publicvoidonTextChanged(CharSequenceinput,intstart,intbefore,int

count){

if(!destinationEditNumber.hasWindowFocus()

||destinationEditNumber.hasFocus()||input==null){

return;

}

Stringstr=input.toString();

if("".equals(str)){

destinationEditNumber.setText("");

return;

}

longt0;

if(BENCHMARK_TEMPERATURE_CONVERSION){

t0=System.currentTimeMillis();

}

try{

doubletemp=Double.parseDouble(str);

doubleresult=(option==Option.C2F)

?TemperatureConverter.celsiusToFahrenheit(temp)

:TemperatureConverter.fahrenheitToCelsius(temp);

StringresultString=String.format("%.2f",result);

destinationEditNumber.setNumber(result);

destinationEditNumber.setSelection(resultString.length());

}catch(NumberFormatExceptionignore){

//WARNINGthisisgeneratedwhilstnumbersarebeingentered,

//forexamplejusta'-'

//sowedon'twanttoshowtheerrorjustyet

}catch(Exceptione){

sourceEditNumber.setError("ERROR:"+e.getLocalizedMessage());

}

if(BENCHMARK_TEMPERATURE_CONVERSION){

longt=System.currentTimeMillis()-t0;

Log.v(TAG,"TemperatureConversiontook"+t

+"mstocomplete.");

}

}

Page 344: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thisisverystraightforward.Wetakethetimesandlogthedifference.Forthis,weareusingtheLog.v()method,andwecanseetheoutputinthelogcatwhenweruntheapplication.YoucancontroltheexecutionofthisbenchmarkbysettingtrueorfalsetotheBENCHMARK_TEMPERATURE_CONVERSIONconstantthatyoudefinedoutsidethemethod.

WhenwelaunchtheactivitywiththeBENCHMARK_TEMPERATURE_CONVERSIONconstantsettotrueinthelogcat,wewillreceivemessagesliketheseeverytimetheconversiontakesplace:

TemperatureConversiontook5mstocomplete.

TemperatureConversiontook1mstocomplete.

TemperatureConversiontook5mstocomplete.

Page 345: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 346: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TimingloggerNow,theonebetterthanthisistheandroid.util.TimingLoggerAndroidclass.TheTimingLoggerobjectcanhelpyoutimeyourmethodcallswithouthavingtoworryaboutmaintainingthosetimevariablesyourself.ItalsohasahigherdegreeofaccuracythanSystem.currentTimeMillis():

privatestaticfinalStringTAG="TemperatureTag";

@Override

publicvoidonTextChanged(CharSequenceinput,intstart,intbefore,int

count){

if(!destinationEditNumber.hasWindowFocus()

||destinationEditNumber.hasFocus()||input==null){

return;

}

Stringstr=input.toString();

if("".equals(str)){

destinationEditNumber.setText("");

return;

}

TimingLoggertimings=newTimingLogger(TAG,"onTextChanged");

timings.addSplit("startingconversion");

try{

doubletemp=Double.parseDouble(str);

doubleresult=(option==Option.C2F)

?TemperatureConverter.celsiusToFahrenheit(temp)

:TemperatureConverter.fahrenheitToCelsius(temp);

StringresultString=String.format("%.2f",result);

destinationEditNumber.setNumber(result);

destinationEditNumber.setSelection(resultString.length());

}catch(NumberFormatExceptionignore){

//WARNINGthisisgeneratedwhilstnumbersarebeingentered,

//forexamplejusta'-'

//sowedon'twanttoshowtheerrorjustyet

}catch(Exceptione){

sourceEditNumber.setError("ERROR:"+e.getLocalizedMessage());

}

timings.addSplit("finishconversion");

timings.dumpToLog();

}

Ifyoulaunchtheapplicationnow,youwillnoticethatnothingcomesoutinyourlogcat.ThisisbecauseTimingLoggerneedsyoutoexplicitlyturnontheloggingfortheTagyoudefined.Otherwise,themethodcallswilldonothing.Fromaterminal,runthefollowingcommand:

adbshellsetproplog.tag.TemperatureTagVERBOSE

TipYoucancheckwhatlevelyourloggingtagissettowiththegetpropcommand:

Page 347: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

adbshellgetproplog.tag.TemperatureTag

Youcanlistallotherpropertiesfromyourdeviceusingthiscommand:adbshellgetprop

Now,whenwelaunchtheapplication,wewillreceivemessagesliketheseeverytimeaconversioncompletes:

onTextChanged:begin

onTextChanged:0ms,startingconversion

onTextChanged:2ms,finishconversion

onTextChanged:end,2ms

Somethingyoushouldtakeintoaccountisthatthesebenchmark-enablingconstantsshouldnotbeenabledintheproductionbuild,asothercommonconstants,suchasDEBUGorLOGD,areused.Toavoidmistakes,youshouldintegratetheverificationoftheseconstants’valuesinthebuildprocessyouareusingforautomatedbuilds,suchasGradle.Further,personally,Iwouldremoveallbenchmarkingorverificationloggingfromthebuildbeforeitshipstoproduction—notcommentoutbutdelete.Rememberthatyoucanalwaysfinditagaininyourversioncontrolsystem,inthehistoryoronabranch.

Loggingcodeexecution’sspeedlikethisissimple,butformorecomplexperformanceissues,youmightwanttousemoredetailed—thoughmorecomplex—techniques.

Page 348: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 349: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

PerformancetestsinAndroidSDKIfthepreviousmethodofaddinglogstatementsdoesnotsuityou,therearedifferentmethodsofgettingperformancetestresultsfromourapplication.Thisisknownasprofiling.

Whenrunninginstrumentedcode(aswithourAndroidinstrumentedtestcases),thereisnostandardwayofgettingperformancetestresultsfromanAndroidapplication,astheclassesusedbyAndroidtestsarehiddenintheAndroidSDKandonlyavailabletosystemapplications,thatis,applicationsthatarebuiltaspartofthemainbuildorsystemimage.Thisstrategyisnotavailableforus,sowearenotdiggingdeeperinthatdirection.Instead,wewillfocusonotheravailablechoices.

Page 350: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

LaunchingtheperformancetestThesetestsarebasedonanapproachsimilartowhatwejustdiscussed,andtheyareusedbyAndroidtotestsystemapplications.Theideaistoextendandroid.app.Instrumentationtoprovideperformancesnapshots,automaticallycreatingaframeworkthatwecanevenextendtosatisfyotherneeds.Let’sunderstandbetterwhatthismeanswithasimpleexample.

CreatingtheLaunchPerformanceBaseinstrumentationOurfirststepistoextendInstrumentationtoprovidethefunctionalityweneed.Weareusinganewpackagenamedcom.blundell.tut.launchperftokeepourtestsorganized:

publicclassLaunchPerformanceBaseextendsInstrumentation{

privatestaticfinalStringTAG="LaunchPerformanceBase";

protectedBundleresults;

protectedIntentintent;

publicLaunchPerformanceBase(){

this.results=newBundle();

this.intent=newIntent(Intent.ACTION_MAIN);

this.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

setAutomaticPerformanceSnapshots();

}

/**

*Launchesintent{@link#intent},

*andwaitsforidlebeforereturning.

*/

protectedvoidlaunchApp(){

startActivitySync(intent);

waitForIdleSync();

}

@Override

publicvoidfinish(intresultCode,Bundleresults){

Log.v(TAG,"Testresults="+results);

super.finish(resultCode,results);

}

}

WeareextendingInstrumentationhere.Theconstructorinitializedthetwofieldsinthisclass:resultsandintent.Attheend,weinvokethesetAutomaticPerformanceSnapshots()method,whichisthekeyheretocreatingthisperformancetest.

ThelaunchApp()methodisinchargeofstartingthedesiredActivityandwaitingbeforereturning.

Thefinish()methodlogstheresultsreceivedandtheninvokestheInstrumentation’sfinish().

Page 351: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingtheTemperatureConverterActivityLaunchPerformanceclassThisclasssetsuptheIntenttoinvokeTemperatureConverterActivityandfurnishtheinfrastructureprovidedbytheLaunchPerformanceBaseclasstotesttheperformanceoflaunchingourActivity:

publicclassTemperatureConverterActivityLaunchPerformance

extendsLaunchPerformanceBase{

@Override

publicvoidonCreate(Bundlearguments){

super.onCreate(arguments);

StringclassName="com.blundell.tut.TemperatureConverterActivity";

intent.setClassName(BuildConfig.APPLICATION_ID,className);

start();

}

@Override

publicvoidonStart(){

super.onStart();

launchApp();

finish(Activity.RESULT_OK,results);

}

}

Here,onCreate()callssuper.onCreate()astheAndroidlifecycledictates.ThentheIntentisset,specifyingtheclassnameandthepackage.ThenoneoftheInstrumentation’smethods,start(),iscalled.Itcreatesandstartsanewthreadinwhichtoruninstrumentation.ThisnewthreadwillmakeacalltoonStart(),whereyoucanimplementtheinstrumentation.

ThentheonStart()implementationfollows,invokinglaunchApp()andfinish().

Page 352: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningthetestsTobeabletorunthistest,weneedtodefinethespecificInstrumentationintheBuild.gradlefileoftheTemperatureConverterproject.

Thisisthesnippetofcodewehavetoaddtotheapp/build.gradle:

defaultConfig{

//othercode

testInstrumentationRunner

"com.blundell.tut.launchperf.TemperatureConverterActivityLaunchPerformance"

}

Onceeverythingisinplace,wearereadytostartrunningthetest.

First,installtheAPKthatincludesthesechanges.Then,wehaveseveraloptionstorunthetests,aswereviewedinpreviouschapters.Inthiscase,weareusingthecommandline,asitistheeasiestwayofgettingallthedetails.Ifyouonlyhaveonedeviceconnected,usethis:

$adbshellaminstrument-w

com.blundell.tut.test/com.blundell.tut.launchperf.TermeratureConverterActiv

ityLaunchPerformance

NoteIfyouareeverwonderingwhatInstrumentationtestrunnersyouhaveinstalledonyourdevice,youcanusethiscommand:adbshellpmlistinstrumentation

Wereceivethesetofresultsforthistestinthestandardoutput:

IINSTRUMENTATION_RESULT:other_pss=7866

INSTRUMENTATION_RESULT:global_alloc_count=4009

INSTRUMENTATION_RESULT:java_allocated=7271

INSTRUMENTATION_RESULT:execution_time=347

INSTRUMENTATION_RESULT:gc_invocation_count=0

INSTRUMENTATION_RESULT:native_pss=0

INSTRUMENTATION_RESULT:received_transactions=-1

INSTRUMENTATION_RESULT:other_shared_dirty=7128

INSTRUMENTATION_RESULT:native_shared_dirty=0

INSTRUMENTATION_RESULT:java_free=4845

INSTRUMENTATION_RESULT:java_size=12116

INSTRUMENTATION_RESULT:global_freed_size=155012

INSTRUMENTATION_RESULT:java_pss=1095

INSTRUMENTATION_RESULT:pre_sent_transactions=-1

INSTRUMENTATION_RESULT:java_private_dirty=884

INSTRUMENTATION_RESULT:pre_received_transactions=-1

INSTRUMENTATION_RESULT:other_private_dirty=6228

INSTRUMENTATION_RESULT:native_private_dirty=0

INSTRUMENTATION_RESULT:cpu_time=120

INSTRUMENTATION_RESULT:sent_transactions=-1

INSTRUMENTATION_RESULT:native_allocated=10430

INSTRUMENTATION_RESULT:java_shared_dirty=8360

Page 353: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

INSTRUMENTATION_RESULT:global_freed_count=1949

INSTRUMENTATION_RESULT:native_free=14145

INSTRUMENTATION_RESULT:native_size=10430

INSTRUMENTATION_RESULT:global_alloc_size=372992

INSTRUMENTATION_CODE:-1

Wehavehighlightedtwoofthevaluesweareinterestedin:execution_timeandcpu_time.TheyaccountforthetotalexecutiontimeandtheCPUtimeusedrespectively.

Runningthistestonanemulatorincreasesthepotentialformismeasurement,becausethehostcomputerisrunningotherprocesses,whichalsotakeuptheCPU,andtheemulatordoesnotnecessarilyrepresenttheperformanceofarealpieceofhardware.

Needlesstosay,inthisandanyothercasewhereyoumeasuresomethingthatisvariableovertime,youshoulduseameasurementstrategyandrunthetestseveraltimestoobtaindifferentstatisticalvalues,suchasaverageorstandarddeviation.

Page 354: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 355: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

UsingtheTraceviewanddmtracedumpplatformtoolsTheAndroidSDKincludesamongitsvarioustoolstwothatarespeciallyintendedtoanalyzeperformanceproblemsandprofiles,andpotentiallydeterminethetargettoapplyoptimizations.AndroidalsooffersustheDalvikDebugMonitorService(DDMS),whichcollatesthesetoolsallinoneplace.DDMScanbeopenedfromAndroidStudiobynavigatingtoTools|Android|DeviceMonitor,orfromthecommandlinewiththecommandmonitor.YoucanuseTraceviewandothertoolsinsideDDMSbyusinghandyGUIshortcuts.Here,however,wearegoingtousethecommand-lineoptionssothatyoucanunderstandthetoolsbehindtheGUI.

Thesetoolshaveanadvantageoverotheralternatives:usually,nomodificationtothesourcecodeisneededforsimplertasks.However,formorecomplexcases,someadditionsareneeded,buttheyareverysimple,aswewillseeshortly.

Ifyoudon’tneedprecisionaboutstartingandstoppingtracing,youcandriveitfromthecommandlineorAndroidStudio.Forexample,tostarttracingfromthecommandline,youcanusethefollowingcommand.Remembertoaddtheserialnumberwith–sifyouhavemultipledevicesattached:

$adbshellamstart-ncom.blundell.tut/.TemperatureConverterActivity

$adbshellamprofilecom.blundell.tutstart/mnt/sdcard/tc.trace

DosomethingsuchasenteringatemperaturevalueintheCelsiusfieldtoforceaconversion,thenrunthis:

$adbshellamprofilecom.blundell.tutstop

$adbpull/mnt/sdcard/tc.trace/tmp/tc.trace

7681KB/s(1051585bytesin0.133s)

$traceview/tmp/tc.trace

Otherwise,ifyouneedmoreprecisionaboutwhenprofilingstarts,youcanaddtheprogrammaticstyle:

@Override

publicvoidonTextChanged(CharSequenceinput,intstart,intbefore,int

count){

if(!destinationEditNumber.hasWindowFocus()

||destinationEditNumber.hasFocus()||input==null){

return;

}

Stringstr=input.toString();

if("".equals(str)){

destinationEditNumber.setText("");

return;

}

if(BENCHMARK_TEMPERATURE_CONVERSION){

Page 356: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Debug.startMethodTracing();

}

try{

doubletemp=Double.parseDouble(str);

doubleresult=(option==Option.C2F)

?TemperatureConverter.celsiusToFahrenheit(temp)

:TemperatureConverter.fahrenheitToCelsius(temp);

StringresultString=String.format("%.2f",result);

destinationEditNumber.setNumber(result);

destinationEditNumber.setSelection(resultString.length());

}catch(NumberFormatExceptionignore){

//WARNINGthisisgeneratedwhilstnumbersarebeingentered,

//forexamplejusta'-'

//sowedon'twanttoshowtheerrorjustyet

}catch(Exceptione){

sourceEditNumber.setError("ERROR:"+e.getLocalizedMessage());

}

if(BENCHMARK_TEMPERATURE_CONVERSION){

Debug.stopMethodTracing();

}

}

Thiswillcreateatracefile,usingthedefaultname,dmtrace.trace,ontheSDcardbyinvokingDebug.startMethodTracing(),whichstartsmethodtracingwiththedefaultlognameandbuffersize.Whenwearedone,wecallDebug.stopMethodTracing()tostoptheprofiling.

NoteRememberthatenablingprofilingreallyslowsdowntheapplicationexecution,sotheresultsshouldbeinterpretedbytheirrelativeweight,notbytheirabsolutevalues.

TobeabletowritetotheSDcard,theapplicationrequiresanandroid.permission.WRITE_EXTERNAL_STORAGEpermissiontobeaddedtothemanifest.

ForTraceviewusingDDMS,thestreamissentthroughtheJDWPconnectionstraighttoyourdevelopmentcomputer,andthepermissionisnotneeded.

Youneedtoexercisetheapplicationinordertoobtainthetracefile.Thisfileneedstobepulledtothedevelopmentcomputertobefurtheranalyzedusingtraceview:

$adbpull/mnt/sdcard/dmtrace.trace/tmp/dmtrace.trace

8491KB/s(120154bytesin0.013s)

$traceview/tmp/dmtrace.trace

Afterrunningthiscommand,thetraceview’swindowappears,displayingalltheinformationcollected,asshowninthisscreenshot:

Page 357: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thetoppartofthewindowshowsthetimelinepanelandacoloredareaforeverymethod.Timeincreasestotherightalongthescale.Therearealsosmalllinesunderthecoloredrow,displayingtheextentofallthecallstotheselectedmethod.

Weprofiledasmallsegmentofourapplication,soonlythemainthreadwasrunningfromourprocess.Inthecaseswhereotherthreadsrunduringtheprofiling,thisinformationwillalsobedisplayed.Forinstance,thisshowsthatanAsyncTaskwasexecutedbythesystem.

Thebottompartshowstheprofilepanel,everymethodexecuted,anditsparent-childrelationships.Werefertocallingmethodsasparentsandthecalledmethodsaschildren.Whenclickedon,amethodexpandstoshowitsparentsandchildren.Parentsareshownwithapurplebackgroundandchildrenwithayellowbackground.

Also,thecolorselectedforthemethod,doneinaround-robinfashion,isdisplayedbeforethemethodname.

Finally,atthebottom,there’saFind:field,wherewecanenterafiltertoreducetheamountofinformationdisplayed.Forexample,ifweareinterestedindisplayingonlythemethodsinthecom.blundell.tutpackage,weshouldentercom/blundell/tut.

Clickingonacolumnwillsettheorderofthelistaccordingtothatcolumninascendingordescendingorder.

Thistableshowsyoutheavailablecolumnsandtheirdescriptions:

Column Description

Name Thenameofthemethod,includingitspackagename,intheformwejustdescribed,whichisbyusing/(slash)asthedelimiter.Also,theparametersandthereturntypearedisplayed.

InclCpuTime% Theinclusivetime,asapercentageofthetotaltime,usedbythemethod.Thisincludesallitschildren.

InclCpuTime

Theinclusivetime,inmilliseconds,usedbytheparticularmethod.Thisincludesthemethodandallitschildren.

Page 358: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ExclCpuTime% Theexclusivetime,asapercentageofthetotaltime,usedbythemethod.Thisexcludesallitschildren.

ExclCpuTime

Theexclusivetime,inmilliseconds.Thisisthetotaltimespentintheparticularmethod.Itexcludesallitschildren.

InclRealTime% Inclusivetimeplusthewaitingtimeoftheprocesstoexecuteasapercentage(waitingforI/O).

InclRealTime Inclusivetimeplusthewaitingtimeoftheprocesstoexecute.

ExclRealTime% Exclusivetimeplusthewaitingtimeoftheprocesstoexecuteasapercentage(waitingforI/O).

ExclRealTime Exclusivetimeplusthewaitingtimeoftheprocesstoexecute.

Calls+Recur

Calls/Total

Thiscolumnshowsthenumberofcallsfortheparticularmethodandthenumberofrecursivecalls.

Thenumberofcallscomparedwiththetotalnumberofcallsmadetothismethod.

CpuTime/Call Thetimeofeverycallinmilliseconds.

ThefinalwordonTraceviewisawordofwarning:TraceviewcurrentlydisablestheJITcompilerfromrunning,whichmaycauseTraceviewtomisattributetimetocodeblocks,whichtheJITmaybeabletowinback.Therefore,itisimperativeaftermakingchangesyouimplyfromTraceviewdata,thatyouensurethattheresultingcodeactuallyrunsfasterwhenrunwithoutTraceview.

Page 359: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 360: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

DmtracedumpDmtracedumpisanalternativetotraceview.Itallowsyoutogenerateyourtracedatainalternativeformats,includingHTML,andalsoacall-stackdiagram,usingthetracefilesalreadygathered.Thelaterdiagramisofatreestructure,andeachnodeofthetreerepresentsonecallinthestack.

Youcanusethesametraceviewfileswehavepulledfromthedevicewiththenewcommand:

dmtracedump–t40–gdmtrace.png/tmp/dmtrace.trace

Whenrunningdmtracedump,ifyougetthedotcommandnotfounderrorandno*.pngfileoutput,itmeansyouneedtoinstallGraphViz.GraphVizcreatesthevisualgraphicaloutputofyourtrace.Youcanreadmoreaboutitanddownloaditatwww.graphviz.org.Onceitisinstalled,yourerrorshouldgoaway.

Thegraphsproducedcanbeverybig,andit’srecommendedthatyoupassadetailedbutpinpointingtracefilesothatyouroutputisdirectedtowardsyourcodeasmuchaspossible,Alternatively,aswejustdid,youcanmakeuseofthe–tparametersothatyouattempttoincludeonlythosechildnodesthattakeupafairamountofCPUtime(suchasyourforegroundappcode).Hereisasnippetofthegraphproducedfromatracewhenweenteratemperatureconversion:

Page 361: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ToviewyourtracedataasHTML,runthefollowing:

dmtracedump–h/tmp/dmtrace.trace>dmtrace.html

ThisalternativeHTMLviewallowsyoutonavigatearoundthedetailsofyourtraceandfilterthecallstacksofeachcall,inawaydifferentfromhowtheoriginaltraceviewGUIdoes:

Page 362: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Thistabledescribestheextracommand-lineargumentsyoucanusewithdmtracedump:

Command Description

-d<trace-

file-name>Carryoutacomparisonagainstthistracefileandprintthedifference.

-g<graph-out-

file-name.png>

Generatethegraphinthisfile.Technically,itmightnotgeneratePNGimages,butifyounameitsomething.png,youcanopenthefiletoseethegraph.

-hTurnontheHTMLoutput.ThiswillbeprintedonyourconsolejustasHTMLcode,soremembertopipethisoutputtoafile,suchasexample.html.

-o Dumpthetracefileinsteadofprofiling.

-s<trace-

file-name>

URLbasetothelocationofthesortableJavaScriptfile(I’mnotsurewhattheuseofthisparameteris!https://code.google.com/p/android/issues/detail?id=53468).

-t<percent>Minimumthresholdforincludingchildnodesinthegraph(thechild’sinclusivetimeasapercentageoftheparent’sinclusivetime).Ifthisoptionisnotused,thedefaultthresholdis20percent.

Page 363: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 364: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

MicrobenchmarksBenchmarkingistheactofrunningacomputerprogramoroperationinordertocompareoperationsinawaythatproducesquantitativeresults,normallybyrunningasetoftestsandtrialsagainstthem.

Benchmarkscanbeorganizedinthefollowingtwobigcategories:

MacrobenchmarksMicrobenchmarks

Macrobenchmarksexistasameanstocomparedifferentplatformsinspecificareassuchasprocessorspeed,numberoffloating-pointoperationsperunitoftime,graphicsand3Dperformance,andsoon.Theyarenormallyusedagainsthardwarecomponents,butcanalsobeusedtotestsoftware-specificareas,suchascompileroptimizationoralgorithms.

Asopposedtothesetraditionalmacrobenchmarks,amicrobenchmarkattemptstomeasuretheperformanceofaverysmallpieceofcode,oftenasinglemethod.Theresultsobtainedareusedtochoosebetweencompetingimplementationsthatprovidethesamefunctionality,whendecidingtheoptimizationpath.

Theriskhereistomicrobenchmarksomethingdifferentthanwhatyouthinkyouaremeasuring.ThisissomethingtotakeintoaccountmainlyinthecaseofJITcompilers,asusedbyAndroid,startingwithversion2.2Froyo.TheJITcompilermaycompileandoptimizeyourmicrobenchmarkdifferentlythanthesamecodeinyourapplication.So,becautiouswhentakingyourdecision.

Thisisdifferentfromtheprofilingtacticintroducedintheprevioussection,asthisapproachdoesnotconsidertheentireapplicationbutasinglemethodoralgorithmatatime.

Page 365: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CalipermicrobenchmarksCaliperisGoogle’sopensourceframeworkforwriting,running,andviewingresultsofmicrobenchmarks.Therearemanyexamplesandtutorialsonitswebsiteathttp://code.google.com/p/caliper.

Caliperisendorsedondeveloper.android.comandisusedbyGoogletomeasuretheperformanceoftheAndroidprogramminglanguageitself.Weareexploringitsessentialusehere,andwillintroducemoreAndroid-relatedusageinthenextchapter.

Itscentralideaistobenchmarkmethods,mainlytounderstandhowefficienttheyare.Wemaydecidethatthisisthetargetforouroptimization,perhapsafteranalyzingtheresultsprovidedbyprofilingtheappviaTraceview.

Caliperbenchmarksuseannotationstohelpyoubuildyourtestscorrectly.BenchmarksarestructuredinafashionsimilartoJUnittests.Previously,CalipermirroredJUnit3initsconventions;forinstance,wheretestshadtostartwiththeprefixtest,benchmarksstartedwiththeprefixtime.Withthelatestversion,itislikeJUnit4whereJUnithas@Test,[email protected],usuallynamedreps,indicatingthenumberofrepetitionstobenchmarkthecodethatsitsinsidethemethod,whichissurroundedbyaloopcountingtherepetitions.

ThesetUp()methodor@Beforeannotationispresentandisusedas@BeforeExperiment.

BenchmarkingthetemperatureconverterLet’sstartbycreatinganewJavamoduleinsideourproject.Yes,thistime,itisnotanAndroidmodule—justJava.

Forconsistency,usethecom.blundell.tutpackageasthemainpackage.

Addadependencytothismoduleonyourcoremoduleinthe/benchmark/build.gradlefile.Thisallowsyoutoaccessthetemperatureconvertercode:

compileproject(':core').

Also,addtheCaliperlibraryasadependency;thisishostedonMavencentral.However,atthetimeofwritingthisbook,theversionreleasedbyGoogleisCaliper1.0-beta-1,whichdoesnotincludetheannotationswehavejustdiscussed.Ihavetriedtopokethemtofixthis,athttps://code.google.com/p/caliper/issues/detail?id=291,starthatissueifyoufeelsoinclined.Therefore,inthemeantime,anotherdeveloperhasreleasedCaliperunderhispackagetoMavencentraltoallowustouseannotations.Thisistheimportyouneed:

compile'net.trajano.caliper:caliper:1.1.1'

CreatetheTemperatureConverterBenchmarkclassthatwillbecontainingourbenchmarks:

publicclassTemperatureConverterBenchmark{

publicstaticvoidmain(String[]args){

CaliperMain.main(CelsiusToFahrenheitBenchmark.class,args);

Page 366: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

}

publicstaticclassCelsiusToFahrenheitBenchmark{

privatestaticfinaldoubleMULTIPLIER=10;

@Param({"1","10","100"})

inttotal;

privateList<Double>temperatures=newArrayList<Double>();

@BeforeExperiment

publicvoidsetUp(){

temperatures.clear();

generateRandomTemperatures(total);

}

privatevoidgenerateRandomTemperatures(inttotal){

Randomr=newRandom(System.currentTimeMillis());

for(inti=0;i<total;i++){

doublerandomTemperature=MULTIPLIER*r.nextGaussian();

temperatures.add(randomTemperature);

}

}

@Benchmark

publicvoidtimeCelsiusToFahrenheit(intreps){

for(inti=0;i<reps;i++){

for(doublet:temperatures){

TemperatureConverter.celsiusToFahrenheit(t);

}

}

}

}

}

WehaveasetUp()methodsimilartoJUnitteststhatusethe@BeforeExperimentannotation.Itisrunbeforethebenchmarksarerun.Thismethodinitializesacollectionofrandomtemperaturesusedintheconversionbenchmark.Thesizeofthiscollectionisafieldandisannotatedherewiththe@ParamannotationsothatCaliperknowsaboutitsexistence.Caliperwillallowustoprovidethevalueofthisparameterwhenwerunthebenchmarks.However,forthisexample,wehavegiventheparamsomedefaultvaluesof"1","10","100".Thismeanswewillhaveatleastthreebenchmarks,withone,then10,andthen100valuesoftemperature.

WeuseaGaussiandistributionforthepseudo-randomtemperatures,asthiscanbeagoodmodeloftherealityofauser.

Thebenchmarkmethoditselfusesthe@Benchmarkannotationsothatcalipercanrecognizeandrunthismethod,inthistimeCelsiusToFahrenheit()instance.Insidethismethod,weloopforthenumberofrepetitionspassedtousasamethodparameter,eachtimeinvokingtheTemperatureConverter.celsiusToFahrenheit()conversion,whichisthemethodwewishtobenchmark.

Page 367: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

RunningCaliperTorunCaliper,right-clickontheclassandselectfromthemenuandrunTemperatureConverterBenchmark.main().Ifyouwanttochangethetotalparameterfromthedefaultof1,10,100,edittherunconfiguration,andintheProgramargumentsfield,input–Dtotal=5,50,500.

Eitherway,thiswillrunthebenchmarks,andifeverythinggoeswell,wewillbepresentedwiththeresults:

Experimentselection:

Instruments:[allocation,runtime]

Userparameters:{total=[1,10,100]}

Virtualmachines:[default]

Selectiontype:Fullcartesianproduct

Thisselectionyields6experiments.

Startingtrial1of6:{instrument=allocation,

benchmarkMethod=timeCelsiusToFahrenheit,vm=default,parameters={total=1}}…

Complete!

bytes(B):min=32.00,1stqu.=32.00,median=32.00,mean=32.00,3rd

qu.=32.00,max=32.00

objects:min=1.00,1stqu.=1.00,median=1.00,mean=1.00,3rdqu.=1.00,

max=1.00

….

Startingtrial6of6:{instrument=runtime,

benchmarkMethod=timeCelsiusToFahrenheit,vm=default,parameters=

{total=100}}…Complete!

runtime(ns):min=158.09,1stqu.=159.52,median=161.16,mean=162.42,3rd

qu.=163.06,max=175.13

Executioncomplete:1.420m.

Collected81measurementsfrom:

2instrument(s)

2virtualmachine(s)

3benchmark(s)

Resultshavebeenuploaded.Viewthemat:

https://microbenchmarks.appspot.com/runs/33dcd3fc-fde7-4a37-87d9-

aa595b6c9224

Tohelpvisualizetheseresults,thereisaservicehostedonGoogleAppEngine(http://microbenchmarks.appspot.com)thatacceptsyourresultdataandletsyouvisualizeitinamuchbetterway.YoucanseethisURLintheprecedingoutput,wheretheresultshavebeenpublished.

Ifyouwishtoaccessasuiteofbenchmarks,orcollateyourresultsovertime,youcanlogintothisserverandgainanAPIkeytohelpcongregateyourresults.Onceyouhaveobtainedthiskey,itshouldbeplacedinthe~/.caliper/config.propertiesfileinyourhomedirectory,andthenexttimeyourunthebenchmarks,theresultswillbelinkedtoyourlogin.

Theconfig.propertieswilllooklikethissnippetafteryoupastedtheAPIkeyobtained:

#Caliperconfigfile

#Runwith--print-configtoseealloftheoptionsbeingapplied

Page 368: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

#INSTRUMENTCONFIG

#instrument.micro.options.warmup=10s

#instrument.micro.options.timingInterval=500ms

#instrument.micro.options.reportedIntervals=7

#instrument.micro.options.maxRuntime=10s

#VMCONFIG

vm.args=-Xmx3g-Xms3g

#SeetheCaliperwebapptogetakeysoyoucanassociateresultswith

youraccount

results.upload.options.key=abc123-a123-123a-b123-a12312312

Theresultwillbeasfollows:

Aswellastherunspeeds,thegeneratedwebsiteshowsyoutheconfigurationoftheJVMusedtorunthetests.Theblueandredsectionsareexpandableforseeingmoreproperties,helpingyoutodetectwhentheenvironmentbeingrunonisactuallyaffectingthedifferentresultsbeingreported.

Page 369: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 370: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryInthischapter,wedissectedtheavailablealternativesfortestingtheperformancemeasuresofourapplicationbybenchmarkingandprofilingourcode.

SomeoptionsthatshouldbeprovidedbytheAndroidSDKarenotavailableatthetimeofwritingthisbook,andthereisnowaytoimplementAndroidPerformanceTestCasesbecausesomeofthecodeishiddenintheSDK.Wevisitedandanalyzedsomeothervalidalternatives.

Amongthesealternatives,wefoundthatwecanusesimplelogstatementsormoresophisticatedcodethatextendsinstrumentation.

Subsequently,weanalyzedprofilingalternativesanddescribedandexemplifiedtheuseoftraceviewanddmtracedump.

Finally,youdiscoveredCaliper,amicrobenchmarkingtoolthathasnativesupportforAndroid.However,weintroduceditsmostbasicusage,andpostponedmorespecificAndroidandDalvikVMusageforthenextchapter.

Tobeabletoquantifyyourtestingeffortsinthenextchapter,wewillbeexecutingcoveragereportsonourcode.WewillalsointroducealternativetestinganddiscussnewupcominglibrariesandtopicsintheAndroidtestingworldtohopefullygiveyousomejumping-offpointstoexploreandcontinueonyourowntestingvoyage.

Page 371: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 372: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Chapter9.AlternativeTestingTacticsUptothispoint,wehaveanalyzedthemostcommonandaccessibletacticstoimplementtestinginourprojects.However,thereareafewmissingpiecesinourpuzzle,whichwe’llhopetocoverinthisfinalchapter.TheAndroidecosystemisalwaysmovingforward,withtheadventofAndroidStudioandGradle.Thetoolboxfortestingisalsoalwaysbeingaddedtoo.Inthisarea,we’lllookatsomethird-partylibrariesthatcanhelpusexpandourtestingframework;suchasRobolectricforAndroidtestingontheJVM,aswellaspotentialbleedingedgeandfuturedevelopments,likeFork;imaginethreadingforyourtests.

Inthischapter,wewillbecoveringthefollowingtopics:

JacococodecoverageRobotiumTestingonhost’sJVMRobolectricFestSpoon/Fork

Page 373: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CodecoveragePerhapsAndroid’sAchilles’heelwouldbethelackofdocumentation,andthenumberofplacesyouhavetovisittogetthecompleteversionofwhatyouaretryingtofind,orwhat’sevenworse,inmanycasestheofficialdocumentationisincorrect,orhasnotbeenupdatedtomatchthecurrentrelease.ThedocumentationforthenewGradlebuildsystemisverysparseontheground,andthisiswheremostpeoplestartwhentryingtoreaduponcodecoverage;solet’slightupafewdarkcorners.

Codecoverageisameasureusedinsoftwaretestingthatdescribestheamountofsourcecodethatwasactuallytestedbythetestsuite,andtowhatdegree,followingsomecriteria.Ascodecoverageinspectsthecodedirectly,itisthereforeaformofwhiteboxtesting.

NoteWhite-boxtesting(alsoknownasclearboxtesting,glassboxtesting,transparentboxtesting,andstructuraltesting),isamethodoftestingsoftwarethattestsinternalstructuresorworkingsofanapplication,asopposedtoitsfunctionality(sayblack-boxtesting).

Fromtheseveraltoolsavailable,providingcodecoverageanalysisforJavaweareusingJacoco,anopen-sourcetoolkitformeasuringandreportingJavacodecoveragethatissupportedbytheAndroidproject.Theinfrastructuretostartusingitforyourownprojectsisalreadythere,therefore,minimizingtheeffortneededtoimplementit.JacocosupersedestheEMMAcodecoveragetool,whiletakingknowledgefromlessonslearnedinthisendeavor,andbeingbuiltbythesameteam.

Jacocodistinguishesitselffromothertoolsbygoingafteradistinctivefeaturecombination;supportforlarge-scaleenterprisesoftwaredevelopment,whilekeepingindividualdeveloper’sworkfastanditerative.ThisisfundamentalinaprojectthesizeofAndroid,andJacocoshinesatitsbest,providingcodecoverageforit.

Page 374: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

JacocofeaturesJava,theAndroidGradlepluginandtheGradlebuildsystem,allhavenativesupportforJacoco.FromthelatestJacocoversionavailableatthisbook’srelease,paraphrasingitsdocumentation,themostdistinctivesetoffeaturesarethefollowing:

Jacococaninstrumentclassesforcoverageeitheroffline(beforetheyareloaded)oronthefly(usinganinstrumentingapplicationclassloader).Supportedcoveragetypes:class,method,line,branch,andinstruction.Jacococandetectwhenasinglesourcecodelineiscoveredonlypartially.Coveragestatsareaggregatedatmethod,class,package,and“allclasses”levels.Outputreporttypes:plaintext,HTML,XML.Allreporttypessupportdrill-downtoauser-controlleddetaildepth.TheHTMLreportsupportssourcecodelinking.Outputreportscanhighlightitemswithcoveragelevels,belowuser-providedthresholds.Coveragedataobtainedindifferentinstrumentationortestrunscanbemergedtogether.Jacocodoesnotrequireaccesstothesourcecodeanddegradesgracefullywithdecreasingamountsofdebuginformationavailableintheinputclasses.Jacocoisrelativelyfast;theruntimeoverheadofaddedinstrumentationissmall(5to20%),andthebytecodeinstrumentoritselfisveryfast(mostlylimitedbyfileI/Ospeed).MemoryoverheadisafewhundredbytesperJavaclass.

Page 375: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 376: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TemperatureconvertercodecoverageTheAndroidGradlepluginhassupportforJacococodecoverageoutofthebox.Thesetupinvolvesselectingwhichbuildflavoryouwanttoobtaincoveragereportsfor,andselectingyourJacocoversion.Wewanttoinstrumentourdebugflavorsothatwecanhavecoveragewithoutaffectingreleasecode.Undertheandroidclosure,addtheselinestoyourandroid/build.gradlefile:

android{

buildTypes{

debug{

testCoverageEnabledtrue

}

}

jacoco{

version='0.7.2.201409121644'

}

}

TheJacocoversiondoesnotactuallyhavetobeaddedhere,however,theversionofJacocoshippingwithAndroidiscurrentlybehindthelatestrelease.ThelatestversionoftheJacococoveragelibrarycanbefoundontheirGitHubpageathttps://github.com/jacoco/jacocoorMavencentral.Therefore,itisrecommendedthatyoumaketheversionexplicit.

Page 377: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GeneratingcodecoverageanalysisreportYouwillneedtohaveanemulatorrunningasJacocoinstrumentsyourandroidtests,andthesearerunonadevicesoanemulatorisappropriate.Whenthetestsarecomplete,acodecoveragereportisgeneratedonthedeviceandthenpulledtoyourlocalmachine.Ifyouchoosetousearealdeviceinsteadofanemulator,itwillneedtoberooted.OtherwisethispullofthereportswillfailwithaPermissionDeniedexception.

Runcodecoveragefromthecommandlineasfollows:

$./gradlewbuildcreateDebugCoverageReport

Alternatively,youcanusethiscommandifyouhavemultipleflavors:

$./gradlewbuildconnectedCheck

Thisfollowingmessageverifiesthatourtestshavebeenrunandthecoveragedataisretrieved:

:app:connectedAndroidTest

:app:createDebugCoverageReport

:app:connectedCheck

BUILDSUCCESSFUL

Thishascreatedthereportfilesinsidethe/app/build/outputs/reports/coverage/debug/directory.Ifyouusemultipleflavors,yourpathwillbeslightlydifferent.

Nowbeforewegoanyfurther,ifyouhaven’trealizedyet,wehavenotonlybeengeneratingthereportfortheAndroidappmodule,butwealsohavecodeinourJavacoremodule.Let’screateareportforthisaswell.

WithGradlehavingsupportforJacoco,weonlyneedtoapplytheJacocoplugintoourcode/build.gradlefile:

applyplugin:'jacoco''jacoco''jacoco''jacoco'''

MoreconfigurationsarepossiblewiththesameclosurethatweareusingforourAndroidmodule.DetailsofpropertiesthatcanbechangedarefoundontheGradleJacocopluginwebsiteathttp://gradle.org/docs/current/userguide/jacoco_plugin.html.

Now,ifyourunthe./gradlewcommandtasks,youshouldseeanewGradletaskthatisgenerated,jacocoTestReport.Runthistasktogeneratecodecoverageforourcoremodule:

$./gradlewjacocoTestReport

Thishascreatedthereportfilesinsidethe/core/build/reports/jacoco/test/directory.

Excellent!Nowwehavecodecoveragereportsforbothourappcodeandourcorecode.

NoteItispossibletotakebothofthesereportsandmergethemintoonefile.Youwillmost

Page 378: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

likelyhavetoworkwiththeXMLoutputtodothis.ThisisleftasataskforthereaderbuttakealookontheJacocowebsiteandtheGradlepluginsiteforhints(ithasbeendonebefore).

Let’sopentheappmodulesindex.htmltodisplaythecoverageanalysisreport.

Theinformationpresentedinthereportincludescoveragemetricsinawaythatallowsdrillingdownintodata,inatop-downfashion,startingwithallclasses,andgoingallthewaytothelevelofindividualmethodsandsourcelines(intheHTMLreport).

ThefundamentalcomponentofcodecoverageinJacocoisthebasicblock;allothertypesofcoveragearederivedfromthebasicblockcoverageinsomeway.Linecoverageismostlyusedtolinktothesourcecode.

ThistabledescribestheimportantpiecesofinformationintheJacococoveragereport:

Label Description

Element Thenameoftheclassorpackage.

MissedInstructions,Coverage

Avisualindicatorshowingthenumberofinstructionsnotcoveredbytests(inred),nexttothepercentageofinstructionscoveredbytests.Example:if(x=1&&y=2)wouldbetwoinstructionsbutonelineofcode.

MissedBranches,Coverage

Avisualindicatorofthenumberofbranchesnotcoveredbytests(inred),nexttothepercentageofbranchescovered.Thinkofanif/elsestatementastwobranches.

Thenumberofbranchesinamethodisagoodmeasureofitscomplexity.

Missed,Cxty

Thenumberofcomplexpaths(cyclomaticcomplexity)missed,nexttothetotalcomplexity.Acomplexitypathisdefinedasasequenceofbytecodeinstructions,withoutanyjumpsorjumptargets.Addingabranchtothecode(anifstatement)wouldaddtwopathways(trueorfalse),thusmakingthecomplexityincreaseby1.However,addinganinstruction(x=1;)wouldnotincreasethecomplexity.

Missed,Lines Thenumberoflinesnotexecutedbyanytest,nexttothetotalnumberoflines.

Page 379: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Missed,Methods

Thenumberofmethodsmissed,nexttothetotalnumberofmethods.ThisisabasicJavamethodthatiscomposedbyagivennumberofbasicpaths.

Missed,Classes Thenumberofclasseswithoutasingletest,nexttothetotalnumberofclasses.

Wecandrill-downfromthepackagetoclasses,tospecificmethods,andthelinescoveredarepresentedingreen,uncoveredonesappearinred,whilepartiallycoveredonesareinyellow.

Thisisanexampleofthereportforthecore/TemperatureConverterclass:

Inthisreport,wecanseethattheclassTemperatureConverterisnot100%covered.Whenwelookintothecode,itistheconstructorthatisnevertested.

Doyouknowwhy?Thinkforamoment.

Yes,becauseaprivateconstructorisnevercalled.Thisisautilityclassthatisnotsupposedtobeinstantiatedatall.

Ifyoucanimaginecreatinganewclasswithjustastaticmethod,youdon’toftencreatetheprivateconstructor;itwouldbeleftasthenon-visibledefaultpublicconstructor.Inthiscase,Ihavebeenratherdiligentandwrotethisprivateconstructor,becauseIwasagoodboyscoutatthetime(andstillam!).

Page 380: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Wecanseeherenotonlyhowthisanalysisishelpingustotestourcodeandfindpotentialbugs,butalsotoimprovethedesign.

Onceweconsiderthisprivateconstructorasasensiblepieceofcodenottoberunningtestsupon,wecanseenowthateventhoughtheclassisnotyet100percentcoveredandthusnotgreen,wecanbeassuredthatthisconstructorwon’tbeinvokedfromanyotherclass.

Ithinkaveryimportantlessonhereis;100percentcodecoveragedoesnothavetobeyourgoal.Understandingyourdomainandthearchitectureofyourapplicationallowsyoutomakemuchmorereachableandrealisticestimatesfortheamountofcodecoveragethat:

GivesyoutheconfidencetochangecodewithoutrepercussionsGivesyoubeliefthattheproductyouwereaskedtodeliver,istheproductyouhavecreated

Page 381: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CoveringtheexceptionsContinuingwithourexaminationofthecoveragereportwillleadustodiscoveranotherblockthatisnotexercisedbyourcurrenttests.Theblockinquestionisthelastcatchinthefollowingtry-catchblockinapp/TemperatureConverterActivity:

try{

doubletemp=Double.parseDouble(str);

doubleresult=(option==Option.C2F)

?TemperatureConverter.celsiusToFahrenheit(temp)

:TemperatureConverter.fahrenheitToCelsius(temp);

StringresultString=String.format("%.2f",",("%.("%."",","result);

destinationEditNumber.setNumber(result);

destinationEditNumber.setSelection(resultString.length());

}catch(NumberFormatExceptionignore){

//WARNINGthisisgeneratedwhilstnumbersarebeingentered,

//forexamplejusta-''''''

//sowedon'tdon'tdon'tdon't'wanttoshowtheerrorjustyet

}catch(Exceptione){

sourceEditNumber.setError("ERROR:"+e.getLocalizedMessage());

}

Firstthingsfirst,whyarewecatchinggenericException?Let’smakethismorespecifictotheerrorweareexpectingtohandle.Thatwaywedon’thandleexceptionswearen’texpecting,andalsoifsomeonereadsthecodetheywillknowexplicitlywhatwearetryingtodohere.

Nowweknowwhatcodeiscausingusnottohavefulltestcoverage,weknowwhatteststowritetothrowthisexceptionandupdateourtestsuiteandourJacocoreport:

}catch(InvalidTemperatureExceptione){

sourceEditNumber.setError("ERROR:"+e.getLocalizedMessage());

}

Weshouldprovideatest,orbetterapairoftests,oneforeachtemperatureunitthatgivenaninvalidtemperatureverifiesthattheerrorisdisplayed.ThefollowingisthetestinTemperatureConverterActivityTestsfortheCelsiuscase,andyoucaneasilyconvertittoprovidetheFahrenheitcase:

publicvoidtestInvalidTemperatureInCelsius()throwsThrowable{

runTestOnUiThread(newRunnable(){

@Override

publicvoidrun(){

celsiusInput.requestFocus();

}

});

getInstrumentation().waitForIdleSync();

//invalidtemplessthanABSOLUTE_ZERO_C

sendKeys("MINUS380");");");");"

Stringmsg="Expectedcelsiusinputtocontainan

error.";.";.";.";"

assertNotNull(msg,celsiusInput.getError());

Page 382: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

}

Werequestthefocusforthefieldundertest.Aswedidbefore,weshouldachievethisbyusingaRunnableontheUIthreadotherwisewewillreceiveanexception.

Thensettheinvalidtemperatureandretrievetheerrormessagetoverifythatitisnotnull.Runningtheend-to-endprocessagain,wecanattestthatthepathisnowcovered,givingustotalcoverageasintended.

Thisistheiterativeprocessyoushouldfollowtochangeasmuchaspossibleofthecodetogreen.Aswassaidbefore,whenthelineofcodeisnotgreen,aslongasyouhaveconsideredtheoptionsandarestillconfidentinchangingothercodewhilethispathisuntested,thenthatisok.

Page 383: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 384: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IntroducingRobotiumOnecomponentofthevastemergingroboticfaunaisRobotium(http://robotium.org),atestframeworkcreatedtosimplifythewritingoftests,requiringminimalknowledgeoftheapplicationundertest.Robotiumismainlyorientedtowritingpowerfulandrobustautomaticblack-boxtestcasesforAndroidapplications.Itcancoverfunction,system,andacceptancetestscenarios,evenspanningmultipleAndroidactivitiesofthesameapplicationautomatically.Robotiumcanalsobeusedtotestapplicationsthatwedon’thavethesourcecodefor,orevenpre-installedapplications.

Let’sputRobotiumtoworkcreatingsomenewtestsforTemperatureConverter.Tokeepourtestsorganized,wecreateanewpackagenamedcom.blundell.tut.robotiuminourTemperatureConverterproject,undertheandroidTestdirectory.WewillinitiallybetestingTemperatureConverterActivity,itisreasonabletocallitTemperatureConverterActivityTests,eventhoughwealreadyhaveaclasswiththesamenameinanotherpackagealsoextendingActivityInstrumentationTestCase2.Afterall,thisclasswillcontaintestsforthissameActivitytoo.

Page 385: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AddingRobotiumLet’saddRobotiumtoourproject,we’llonlybeusingitintestcasesandsoitshouldgoonthetestcaseclasspath.Asofthiswriting,thelatestversionofRobotiumis5.2.1.Inapp/build.gradle,weaddthefollowing:

dependencies{

...

androidTestCompile('com.jayway.android.robotium:robotium-solo:5.2.1')

}

Page 386: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CreatingthetestcasesFromthepreviouschapters,weknowthatifwearecreatingtestcasesforanActivitythatshouldrunconnectedtothesysteminfrastructure,weshouldbaseitonActivityInstrumentationTestCase2,andthatiswhatwearegoingtodo.

ThetestFahrenheitToCelsiusConversion()testMoreorlessthetestcaseshavethesamestructureasotherInstrumentation-basedtests.ThemaindifferenceisthatweneedtoinstantiateRobotium’sSolointhetestsetUp(),andcleanupRobotiuminthetearDown():

publicclassTemperatureConverterActivityTestsextends

ActivityInstrumentationTestCase2<TemperatureConverterActivity>{

privateTemperatureConverterActivityactivity;

privateSolosolo;

publicTemperatureConverterActivityTests(){

super(TemperatureConverterActivity.class);

}

@Override

protectedvoidsetUp()throwsException{

super.setUp();

activity=getActivity();

solo=newSolo(getInstrumentation(),activity);

}

@Override

protectedvoidtearDown()throwsException{

solo.finishOpenedActivities();

super.tearDown();

}

}

ToinstantiateSolo,wehavetopassareferencetotheInstrumentationclassandtotheActivityundertest.

Ontheotherhand,tocleanupSoloweshouldcallthefinishOpenedActivities()method.ThiswillfinalizeSoloandthenfinishourActivity,andwetheninvokesuper.tearDown().

SoloprovidesavarietyofmethodstodriveUItestsandsomeassertions.Let’sstartbyre-implementingthetestFahrenheitToCelsiusConversion()thatwepreviouslyimplementedusingtheconventionalapproach,butinthiscaseusingSolofacilities:

publicvoidtestFahrenheitToCelsiusConversion(){

solo.clearEditText(CELSIUS_INPUT);

solo.clearEditText(FAHRENHEIT_INPUT);

solo.clickOnEditText(FAHRENHEIT_INPUT);

solo.enterText(FAHRENHEIT_INPUT,"32.5");

solo.clickOnEditText(CELSIUS_INPUT);

doublef=32.5;

Page 387: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

doubleexpectedC=TemperatureConverter.fahrenheitToCelsius(f);

doubleactualC=

((EditNumber)solo.getEditText(CELSIUS_INPUT)).getNumber();

doubledelta=Math.abs(expectedC-actualC);

Stringmsg=f+"F->"+expectedC+"C"

+"""""butwas"+actualC+"C(delta"+delta+")";

assertTrue(msg,delta<0.005);

}

Thisisprettysimilar,however,thefirstdifferenceyoumayhavenoticedisthatinthiscasewearenotgettingreferencestotheUIelementsaswepreviouslydidinthesetUp()method,usingfindViewById()tolocatetheview.However,weareusingoneofthebiggestadvantagesofSolo,whichislocatingtheviewsforususingsomecriteria.Inthiscase,thecriterionistheorderinwhichtheEditTextappears.Thesolo.clearEditText(intindex)methodexpectsanintegerindexofthepositiononthescreenstartingfrom0.Consequently,weshouldaddtheseconstantstothetestcase,justlikeinouruserinterfacetheCelsiusfieldisontop,andFahrenheitbeneath:

privatestaticfinalintCELSIUS=0;

privatestaticfinalintFAHRENHEIT=1;

TheotherRobotiummethodsfollowthesameconvention,andwearesupplyingtheseconstantswhennecessary.Thistestisverysimilartotheoneincom.blundell.tut.TemperatureConverterActivityTest,butyoumayhavenoticedthatthereisasubtledifference.Robotiumislocatedatamuchhigherlevelandwedon’thavetoworryaboutasmanyinternalsorimplementationdetails;forexample,wheninourprevioustestweinvokedcelciusInput.requestFocus()totriggertheconversionmechanism,herewejustsimulatewhattheuserdoesandissueasolo.clickOnEditText(CELSIUS).

Wesimplifiedthetestsensibly,butthebiggestadvantageofusingSoloisyettocome.

TestingbetweenActivitiesAsRobotiumissituatedatamuchhigherlevel,andwedon’tdealwithimplementationdetails,itisnotourproblemifanewActivityislaunchedwhenweclickonanAndroidwidget;weonlytreatthiscasefromtheUIperspective.

Here,Iamgoingtodiscusssomefunctionalitytheoretically.Thishasnotyetbeencreatedandisleftuptotheuserasafurtherstep,ifyousowish.

Nowthatwehaveaworkingtemperatureconverter,itwouldbeniceifwecouldlettheuserdecideuptohowmanydecimalplacestheywanttoseeaconversion.Allowingtheusertochangethisoption,viaanAndroidDialog,soundslikeasensibleoption.

Ourpurposeistochangethevalueofdecimalplacespreferencetofive,andverifythatthechangeactuallytookplace.BecauseofthehighlevelofRobotium,thistestisreadableandunderstandablewithoutactuallyhavingthefunctionalityimplemented.ThisisanexampleofaBDDapproachtoimplementthisfeature.

Thefollowingcodesnippetillustratesthedetailsofthetest:

Page 388: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

publicfinalvoidtestClickOptionMenuSavesDecimalPreference(){

intdecimalPlaces=5;

StringnumberRegEx="^[0-9]+$";

solo.sendKey(Solo.MENU);

solo.clickOnText("Preferences");

solo.clickOnText("Decimalplaces");

assertTrue(solo.searchText(numberRegEx));

solo.clearEditText(DECIMAL_PLACES);

assertFalse(solo.searchText(numberRegEx));

solo.enterText(DECIMAL_PLACES,Integer.toString(decimalPlaces));

solo.clickOnButton("OK");

solo.goBack();

solo.sendKey(Solo.MENU);

solo.clickOnText("Preferences");

solo.clickOnText("Decimalplaces");

assertTrue(solo.searchText(numberRegEx));

inteditTextDecimalPlaces=

Integer.parseInt(solo.getEditText(DECIMAL_PLACES)

.getText().toString());

assertEquals(decimalPlaces,editTextDecimalPlaces);

}

Therearenogorydetailsabouthowsharedpreferencesandoptionsmenusareimplemented.Weonlytestitsfunctionality.WestartbypressingtheMENUkeyandclickingonPreferences.

Wow,wejustspecifiedthemenuitemtitleandthat’sit!

ThenewActivityhasstarted,butwedon’thavetoworryaboutthatimplementationdetail.WecontinueandclickonDecimalplaces.

Weverifythatsomefieldcontaininganumber,thepriorvalueofthispreference,appeared.DoyourememberwhatIsaidaboutregularexpressions?Theyalwayscomeinhandyinonewayoranother,tomatchanydecimalintegernumber(anydigitfollowedbyzeroormoredigits).Then,weclearthefieldandverifythatitwasinfactcleared.

Weenterthestring,representingthenumberwewanttouseasapreference,5inthiscase.ClickontheOKbuttonandthepreferenceissaved.

Finally,weneedtoverifythatitactuallyhappened.Thesameprocedureisusedtogetthemenuandthefield.Finally,weverifythattheactualnumberisalreadythere.

YoumaywonderwhereDECIMAL_PLACEScomefrom.WepreviouslydefinedCELSIUSandFAHRENHEITindexconstantsforthefieldsonthescreen,andthisisthesamecase,becausethiswillbethethirdEditTextweshoulddefineinourclass:

privatestaticfinalintDECIMAL_PLACES=2;

TestscanberunfromyourIDEorthecommandline,accordingtoyourpreferences.

Page 389: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 390: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Testingonthehost’sJVMWeleftthissubjectfortheendofthischapter,asitseemsthisistheHolyGrailoftheAndroidplatform.

AndroidisbasedonavirtualmachinenamedDalvik,afteravillageinIceland,optimizedformobileresourceswithlimitedcapabilitiessuchasconstrainedamountofmemoryandprocessorspeed.Thusrepresentativeofamobiledevicebutcertainlyaverydifferentenvironmentthanourmemoryrichandspeedyhostcomputers,typicallyhavingplentyofmemoryandprocessorspeedtoenjoy.

Ordinarily,werunourapplicationsandtestsonanemulatorordevice.ThesetargetshaveamuchslowerrealoremulatedCPU.Thus,runningourtestsisatime-consumingactivity,mainlywhenourprojectstartstogrow.ApplyingTest-drivenDevelopmenttechniquescompelsustorunhundredsofteststoverifyeverychangeweintroduced.

NoteIt’sworthnoticingthatthistechniquecanbeusedonlyasaworkaroundduringthedevelopmentprocesstospeedthingsup,anditshouldneverreplacefinaltestingontherealplatform,asincompatibilitiesbetweentheDalvikandJavaSEruntimemayaffecttheaccuracyofthetests.

Wearehalfwaytherealreadywiththecreationofourcoremodule.NowweareintheJavaworldandfreetorunourtestsontheJVM(anduseJUnit4,comingtoanAndroidnearyousoon).Thereisone-waydependencyfromtheappAndroidmoduletothecoreJavamodule.AllowingustofreeourselvesfromtheshacklesofAndroidtesting,encumbrancewhenrunningtestsinthecoremodule.

Later,weshouldfindoutamethodthatallowsustointerceptthestandardcompilation-dexing-runningonanemulatororadevicesequence,andbeabletorunAndroidonourhostcomputerdirectly.

Page 391: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

ComparingtheperformancegainAquickreminderaboutthespeedgainwhenrunningtheseJava-onlytestscomparedtoAndroidinstrumentationtests.

Thedistinctionisevident.Thereisnoemulatorstartup,oranydevicecommunication,andthereforethespeedgainisimportant.Analyzingtheevidence,wecanfindoutthesedifferences.

Runningalltestsinmydevelopmentcomputertakes0.005seconds;withsometeststakingsolittletimethattheyarenotevenaccountedfor,andaredisplayedas0.000seconds.

IfImovetheseteststoourappmodule,andrunthesametestsontheemulator,thismakesthehugedifferenceevident.Thesesameteststook0.443secondstorun,almost100timesmore,andthat’sahugedifferenceifyouconsiderhundredsoftestsrunning,tensoftimesaday.

Itisalsogoodtonoticethatotheradvantagesexist,besidesthespeedgain,andtheyaretheavailabilityofyearsofJava,tooling,library,andplugincreation,includingseveralmockframeworksandcodeanalysistools.

Page 392: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AddingAndroidtothepictureWeintentionallyleftAndroidoutsideourpicture.Let’sanalyzewhathappensifweincludeasimpleAndroidtestinsidecore.RememberthatforanAndroidtesttocompileandroid.jarfromtheSDK,itshouldalsobeaddedtothemodules’libraries.

Andhereiswhatweobtain:

java.lang.RuntimeException:Stub!

atandroid.content.Context.<init>(Context.java:4)

atandroid.content.ContextWrapper.<init>(ContextWrapper.java:5)

atandroid.app.Application.<init>(Application.java:6)

NoteAddingtheandroid.jartotheclasspathforcoreisslightlyawkwardandlongwinded.Itisnotsomethingthatisdonebydefault.ThisisagoodthingasitstopsusaccidentallyusingAndroid-specificclasseswhenwritingcodeinsidecore.

Thereasonisthatandroid.jarprovidesonlytheAPI,nottheimplementation.Allmethodshavethesameimplementation:

thrownewRuntimeException("Stub!");

IfwewanttocircumventthislimitationtotestsomeclassesoutsideoftheAndroidoperatingsystem,weshouldcreateanandroid.jarthatmockseveryclass.However,wewouldalsofindproblemsforsubclassesofAndroidclasses,likeTemperatureConverterApplication.Thiswouldbeadauntingtaskandasignificantamountofwork,soweshouldlookforanothersolution.

Page 393: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 394: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IntroducingRobolectricRobolectric(http://robolectric.org)isaunittestframeworkthatinterceptstheloadingofAndroidclassesandrewritesthemethodbodies.Robolectricre-definesAndroidmethodssotheyreturndefaultvalues,suchasnull,0,orfalse.Ifavailable,itforwardsmethodcallstoshadowobjects,mimickingAndroidbehavior.

Alargenumberofshadowobjectsareprovided,butthisisfarfromcompletecoverage,however,itisimprovingconstantly.Thisshouldalsoleadyoutotreatitasanevolvingopensourceproject,forwhichyoushouldbereadytocontributetomakeitbetter,butalsotodependonitwithcautionbecauseyoumaydiscoverthatwhatyouneedforyourtestshasnotbeenimplementedyet.Thisisnotinanywaytodiminishitsexistingprospects.

Page 395: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

InstallingRobolectricRobolectriccanbeinstalledbyusingthelatestRobolectricJARfromtheMavencentralrepository.Atthetimeofthiswriting,thelatestavailableisversion2.4:

testCompile'org.robolectric:robolectric:2.4'

Usually,addingadependencyisassimpleasthisoneline,however,withRobolectricabitofjiggerypokeryisneededforittoworkwiththeGradlebuildtypes.

First,Robolectrictestsrequiretheirownmoduletorunin.Thisisnothingnew.CreateanewJavamodule,we’llcallitrobolectric-tests.Keepthepackagethesameasalwayscom.blundell.tut.Now,wehavetomodifytherobolectric-tests/build.gradle,sowecanhookRobolectricinplaceoftheandroid.jar:

defandroidModuleName=":app";

defflavor="debug"

evaluationDependsOn(androidModuleName)

applyplugin:'java'

dependencies{

defandroidModule=project(androidModuleName)

testCompileproject(path:androidModuleName,

configuration:"${flavor}Compile")

defdebugVariant=androidModule.android.applicationVariants

.find({it.name==flavor})

testCompiledebugVariant.javaCompile.classpath

testCompiledebugVariant.javaCompile.outputs.files

testCompilefiles(

androidModule.plugins.findPlugin("com.android.application")

.getBootClasspath())

testCompile'junit:junit:4.12'

testCompile'org.robolectric:robolectric:2.4'

}

Thisisabigchunkofconfigurationtotakein,let’sbreakitdownintosteps.

Firstly,wedefinethemodulenameforourAndroidapplication,andthenwenametheflavorthatwewillwanttotestagainst.

TheEvaluationDependsOnclasstellsGradletoensurethatourapplicationmoduleisevaluatedbeforeourtests,thisstopsanystrangeerrorsfromorderofexecutionquirks.

Next,weapplythejavapluginaspernormalconventionforaJavaproject.

ThedependenciesclosureiswhereweaddalloftheAndroiddependenciestoourclasspath.First,weaddtheselectedbuildvariantofourmodule,debug,thentheclasspathanditsdependencies,alsoensuringwehavesystemdependenciesfromourAndroidplugin.

Page 396: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Lastly,weapplyJUnit4andRobolectricastestdependencies.

NoteRemember,ifyouhavemultipleproductflavorsandbuildtypes,thenthisconfigurationneedsthefullbuildvariantaddingtothescript.Itwouldbeprettystraightforwardtoamendthisbuildscript.

Page 397: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

AddingresourcesWhenyourunyourtests,RobolectricattemptstolookupyourAndroidManifest.xmlsoitcanfindresourcesforyourapplication,andknowaboutyourtargetSDKversion,amongotherproperties.WiththecurrentRobolectricversionandourchoiceofusingaseparatemodule,RobolectriccannotfindyourresourcesoryourAndroidmanifest.Youcanstillwritetestsandgetfeedbackwithoutthisoptionalstep,butyoumayfindsomestrangenesswhenaccessingclassesthatuseresources;forexample,R.string.hello_world,andwillgetmessageslikethisinyourconsole:

WARNING:Nomanifestfilefoundat./AndroidManifest.xml.Fallingbackto

theAndroidOSresourcesonly.Toremovethiswarning,annotateyourtest

classwith@Config(manifest=Config.NONE).

Thiscanbefixedbydoingasitsayswithan@Configannotation,orcreatingacustomtestrunnerthatspecifiesthemanifestlocationoraswechoosetodohere,creatingaconfigurationfileandaddingittoyourclasspath.Insidetherobolectric-testsmodule,createthefolder/src/test/resources,andcreateafileorg.robolectric.Config.properties.ThiswillcontainourAndroidmanifestlocation;itwillalsocontainourminimumSDKversion,aswedon’tstatethisinourmanifest.Itwillhavethesecontents:

manifest=../app/src/main/AndroidManifest.xml

emulateSdk=16

NoteRobolectricattemptstolookupyourminimumSDKinsidetheAndroidManifest.xml.However,withtheGradlebuildsystemyoudonotdeclareithere,butdeclareitintheapp/build.gradle.

WearenowsetupandreadytocreatesomeRobolectrictests!

Page 398: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

WritingsometestsWewillgetacquaintedwithRobolectricbyreproducingsomeofthetestswewrotebefore.Onegoodexamplecanbere-writingtheEditNumbertests.Let’screateanewEditNumberTestsclass,thistimeinthenewlycreatedproject,andcopythetestsfromtheEditNumberTestsclassintheTemperatureConverterTestproject:

@RunWith(RobolectricTestRunner.class)

publicclassEditNumberTests{

privatestaticfinaldoubleDELTA=0.00001d;

privateEditNumbereditNumber;

Intheprevioussnippet,wedeclarethetestrunnerwiththe@RunWithannotation.ThenwedefinedtheeditNumberfield,toholdthereferencetotheEditNumberclass:

@Before

publicvoidsetUp()throwsException{

editNumber=newEditNumber(Robolectric.application);

editNumber.setFocusable(true);

}

Thissnippetcomprisestheusualsetup()method.InthesetUp()method,wecreatedanEditNumberwithanapplicationcontext,andthenwesetitasfocusable.Thecontextisusedtocreatetheview,andRobolectrichandlesthisforus:

@Test

publicfinalvoidtestClear(){

Stringvalue="123.45";";";";"

editNumber.setText(value);

editNumber.clear();

assertEquals("",editNumber.getText().toString());

}

@Test

publicfinalvoidtestSetNumber(){

editNumber.setNumber(123.45);

assertEquals("123.45",editNumber.getText().toString());

}

@Test

publicfinalvoidtestGetNumber(){

editNumber.setNumber(123.45);

assertEquals(123.45,editNumber.getNumber(),DELTA);

}

Inthislastsnippet,wehavethebasicteststhatarethesameastheEditNumbertestsofourpreviousexamples.

Wearehighlightingthemostimportantchanges.Thefirstoneistospecifythetestrunner

Page 399: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

JUnitthatwilldelegatetheprocessingoftheteststo,[email protected],weneedtouseRobolectricTestRunner.classastherunner.ThenwecreateanEditTextclass,usingaRobolectricContext,asthisisaclassthatcouldn’tbeinstantiatedwithoutsomehelp.Finally,aDELTAvalueisspecifiedintestGetNumberasassertEqualssince,thefloatingpointnumberrequiresitinJUnit4.Additionally,weaddedthe@Testannotationtomarkthemethodastests.

TheothertestmethodsthatexistedintheoriginalEditNumberTestscannotbeimplemented,orsimplyfailforavarietyofreasons.Forexample,aswementionedbefore,Robolectricclassesreturndefaultvalues,suchasnull,0,false,andsoon,andthisisthecaseforEditable.Factory.getInstance(),whichreturnsnullandcausesthetesttofail;becausethereisnootherwayofcreatinganEditableobject,weareatadeadend.

Similarly,theInputFilterthatEditNumbersetsisnonfunctional.Itisfutiletocreateatestthatexpectssomebehavior.

ThealternativetotheseshortcomingswouldbetocreateShadowclasses,butthisrequiresalterationoftheRobolectricsourceandthecreationofRobolectric.shadowOf()methods.Thisprocedureisdescribedinthedocumentationthatyoumayfollow,ifyouareinterestedinapplyingthisapproachtoyourtests.

Havingidentifiedtheseissues,wecanproceedtorunthetests,andtheywillruninthehost’sJVMwithnoneedtostartorcommunicatewithanemulatorordevice.

Page 400: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 401: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Google’smarchonshadowsForsomereason,GoogledoesnotlikeRobolectric,they’veneveracknowledgedthatitworks,orneversaidthatit’sasolutiontoaproblem.Iftheyignorethesolution,thenthatmeanstheproblemofslowrunningtestsdoesn’texist,right.TheyseemtofeelthatRobolectricdetractsfromAndroid,andsohavekindofpubliclygivenitthecoldshoulder.Surreptitiouslypushingitawaybyignoringitsexistence,thatisupuntilnow.

Googlehascreatedexactlywhatwesaidbefore,anandroid.jarfilewithdefaultmethodimplementations.Thismeansnomorestub!errorswhenaccessingamethod.Further,theyhaveremovedallofthefinalmodifiersfromclasses,allowingmockingFrameworkstohaveafieldday.Unfortunately,atthetimeofthiswritingitisundocumented.Nosurprise!Idon’twanttogiveusagesteps,aswhileundocumentedthesewillbechangingrapidly.However,whatIwillsayis,ifGooglegotthisright,thenitmeansforthetestingscenariodescribedpreviously,Robolectricisoutofthewindow,andwecanusethestandardAndroidtestingSDKs.Thesameprincipleswillapply,andsoIthinkit’sstillvaluableifyouunderstandhowRobolectricworks.YoucanapplythisunderstandingtothefuturethatIcannot.

Page 402: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 403: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IntroducingFestAnotherweaponforourtestingarsenalisbettertestingassertions.Haveyounoticedhowsometimesstacktracesforfailedtestsarereallyunfriendlyand/ormysticallywrong?Theygiveyoulittleinformationabouttherealfailureandyouendupconfused,havingtoreadtheentiresourcetofathomouthowtofixtheproblem.

Asanexample,lookatthisassertion:

org.junit.Assert.assertEquals(3,myList.size());

Weareassertingthatacollectionofobjectsaftersometaskhasasizeofthree,lookatourerrormessagewhenthetestfails:

java.lang.AssertionError:

Expected:3

Actual:2

Ok,thatkindofmakessense,butit’sabitabstract.Whatitemismissingfromourlist?Iamgoingtohavetorunthetestsagaintofindout,orIcouldaddacustomerrormessage:

assertEquals("Listnotthecorrectsize"+myList,

3,myList.size());

Givingmetheerrormessage:

java.lang.AssertionError:Listnotthecorrectsize[A,B]

Expected:3

Actual:2

Thaterrormessageismuchbetter.ItshowsI’mmissingCfrommylist.However,lookingbackattheassertion,it’sgettingkindofunreadable.Sometimes,ataglance,itmightevenappearlikeIamtryingtoassertwhetherthatinitialstringisequaltotheothervars,theparameterorderingdoesnothelpatall.WhatifIhadanotherobjectthatdoesn’tsoeasilyimplementtoString?Iwouldneedtocreatemorecustomcodetoprintaniceerrormessage,probablyrepeatingmyselfquitealotwithboilerplateerrormessages.

Stopallthatworryingrightnow!TakealookathowwecandothesameassertionwithFest:

org.fest.assertions.api.assertThat(myList).hasSize(3);

Now,ourerrormessagelookslike:

java.lang.AssertionError:expectedsize:<3>butwas:<2>in:<['A','B'']>

Nice,withnoextraeffortbyus,wegetanerrormessageshowinguswhatisinthelistandhowthesizesdifferentiate.Alsolookingbackattheassertion,it’smuchmorereadableandevencodingitwaseasierwiththefluidinterface.Thisimprovesthereadabilityofourtestcode,andspeedsupdebuggingandtestfixing.

Afterdoingthischange,IcametorealizeweactuallymighthavewantedtotestthecontentsoftheList,butduetotheencumbranceoftheJUnitassertions,wewerenot

Page 404: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

bothering.Festtotherescueoncemore:

assertThat(myList).contains("A",""B",""C");

output:

java.lang.AssertionError:expecting:

<['A',]>

tocontain:

<['A','B','C']>

butcouldnotfind:

<['C']>

ThinkhowwewouldhavehadtodothatwithJUnitassertions,andIthinkyou’llappreciatethepowerofFest.

Festcomesinmultipleflavorsforassertionsondifferentlibraries;theseincludethejavaflavor,asshownpreviously,andanAndroidflavor,whichallowsyoutodofluid-styleinterfaceassertionsonAndroidcomponents,likeViewsandFragments.HereisanexampleofJUnitassertingvisibility,andthenFest:

assertEquals(View.VISIBLE,layout.getVisibility());

assertThat(layout).isVisible();

AddingeitherlibrarytoyourprojectisjustanotherGradledependency,thelatestversionscanbefoundonMavencentral.HereistheexampleforJavafest,thelatestatthetimeofwriting:

testCompile'org'.easytesting:fest-assert-core:2.0M10'

NoteNote,thatAndroidFesthasbeenrebrandedintoAssert-Jandissplitintomanydependenciesdependingonwhatyouwanttotest.Theassertionswillworkexactlythesameway.Moreinformationandinstructionstoaddasadependencycanbefoundathttps://github.com/square/assertj-android.

Page 405: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 406: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IntroducingSpoonDevicefragmentationisalwaystalkedaboutaroundAndroidanditissomethingyoushouldbeconsiderateof.Thenumberofdifferentdevicesandformfactorsmeansyoureallyneedtobeconfidentthatyourapplicationrunswell,onalltheaforementioned.Spoonisrightheretohelp;Spoon(http://square.github.io/spoon)isanopen-sourceprojectthatgivesyouatestrunnerthatallowsinstrumentationteststoberunonallconnecteddevicesinparallel.Italsoallowsyoutotakescreenshotsasthetestsarerunning.Notonlydoesthisspeedupyourtestingandfeedbackcycle,italsoallowsyoutopotentiallyvisuallyseewheretestswentwrong.

Spooncanbeaddedtoyourprojectwiththisdependency:

testCompilecom.squareup.spoon:spoon-client:1.1.2

Youcanthentakescreenshotsinsideyourtests,allowingyoutoseethestateofyourapplicationwhenyouarealsoassertingbehavior:

Spoon.screenshot(activity,"max_celcius_to_fahrenheit");

Ifyoutakethescreenshotrightbeforeyourassertion,youcanusethescreenshotstohelpyoudeterminefailures.AnothercoolfeatureisSpoonwillcollateyourscreenshotsfromonetestintoananimatedGIF.soyoucanwatchthesequenceofevents.

Spoonisthenrunfromthecommandline,usingthiscommand:

$java-jarspoon-runner-1.1.2-jar-with-dependencies.jar\

--apkandroidApplicationTestGuide.apk\

--test-apkandroidApplicationTestGuideTests.apk

NoteYoucanfindyourAPKfilesinsidethe/build/folder.IfyouneedmoreinformationofusingtheAPKfilesinthisway,andtestingfromthecommandline,takealookbackatChapter7,Behavior-drivenDevelopment.

Page 407: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 408: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IntroducingForkAnotherhumorousnameforalibrary,butstickwithitreader,thissimilarityisnotjustaco-incidence.AftertellingyouhowamazingSpoonisatspeedingupyourtestsbyrunningallyourinstrumentationtestsinparallelonallconnecteddevices,wellherecomesFork,totellyouthatthisnaïvescheduling(theirwordsnotmine),isaburdenonyourselfandyourCI.Forkcanrunyourtestsevenfaster!

Forkincreasesyourtests’speedbyintroducingaconceptcalledDevicePools.Insimpleterms,imagineyouhadtwoidenticaldevices,whicharetwoSonyXperiaZ1srunningAndroid5.0.Forkwilltakeyourtestsuiteandsplititinhalf,runninghalfthetestsoneachdevice.Thus,itsavesyou50percentofthetestrunspeed(roughlyexcludingwarmup/setuptime).

Thesedevicepoolscomeindifferentflavorsforthingssuchas,apilevel,smallestwidth,tabletdevices,ormanualpools,whereyoudeclarethedeviceserialidyouwanttouse.Moreinformationaboutdevicepoolsandcustomparametersfortheforktaskcanbefoundathttp://goo.gl/cIm6GQ.

ForkcanbeusedwithGradle,byaddingtheplugintoyourbuildscriptandapplyingit:

buildscript{

dependencies{

classpath'com'.shazam.fork:fork-gradle-plugin:0.10.0'

}

}

applyplugin:'fork'

Now,youcanrunforktestsinsteadofyournormalinstrumentationtestswiththiscommand:

./gradlewfork

NoteIfyouhavemultipleflavorsinyourproject,youcanseewhatforktasksareavailablewiththecommand:./gradlewtasks|grepfork.

SpoonandForkarepowerfultools,andcombinednowwithyourknowledgeofinstrumentationtests,unittesting,benchmarking,andcodeanalysis,youcanputtogetherarobust,informational,andwell-roundedtestsuite,whichgivesyouconfidenceandagilitywhenitcomestowritingyourAndroidapplications.

Page 409: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the
Page 410: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SummaryThischapterhasbeenalittlemoreinvolvedthanpreviousones,withthesoleintentionoffacingrealisticsituationsandstate-of-the-artAndroidtesting.

WestartedbyenablingcodecoveragethroughJacoco,runningourtests,andobtainingadetailedcodecoverageanalysisreport.

Wethenusedthisreporttoimproveourtestsuite.Writingteststocovercodewewerenotawarehadnotbeentested.Thisledustobettertests,andinsomecasesimprovedthedesignoftheprojectundertest.

WeintroducedRobotium,averyusefultooltoeasethecreationoftestcasesforourAndroidapplications,andweimprovedsometestswithit.

ThenweanalyzedoneofthehottesttopicsinAndroidtesting;testingonthedevelopmenthostJVM,optimizing,andreducingconsiderablythetimeneededtorunthetests.SomethingthatishighlydesirablewhenweareapplyingTest-drivenDevelopmenttoourprocess.Withinthisscope,weanalyzedRobolectricandcreatedsometestsasdemonstrationstogetyoustartedonthesetechniques.

Toroundoffourknowledge,welookedatFestandsomecutlerythesecanhelpushavemoreexpressivetests,improvedfeedback,andamorepowerfuloveralltestsuite.

WehavereachedtheendofthisjourneythroughtheavailablemethodsandtoolsforAndroidtesting.Youshouldnowbemuchbetterpreparedtostartapplyingthistoyourownprojects.Theresultswillbevisibleassoonasyoubegintousethem.

Finally,IhopethatyouhaveenjoyedreadingthisbookasmuchasIdidwritingit.

Happytesting!

Page 411: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

IndexA

AccessPrivateDataTestclass/Androidunittestsactivities

testing/Testingactivitiesandapplications,TestingactivitiesActivityInstrumentationTestCase2class

about/TheActivityInstrumentationTestCase2classconstructor/TheconstructorsetUpmethod/ThesetUpmethodtearDownmethod/ThetearDownmethod

ActivityInstrumentationTestCase2.getActivity()method/CreatingthefixtureActivityManager

URL/InstrumentationActivityMonitorinnerclass

about/TheActivityMonitorinnerclassexample/Example

ActivityTestCaseclassabout/TheActivityTestCaseclassscrubClassmethod/ThescrubClassmethod

Androidunittests/Androidunittests

android-test-kitURL/TestingwithEspresso

android.test.mocksubpackageMockApplicationclass/MockobjectsMockContentProviderclass/MockobjectsMockContentResolverclass/MockobjectsMockContextclass/MockobjectsMockCursorclass/MockobjectsMockDialogInterfaceclass/MockobjectsMockPackageManagerclass/MockobjectsMockResourcesclass/Mockobjects

Androidapplicationsbuildingmanually,Gradleused/BuildingAndroidapplicationsmanuallyusingGradle

AndroidEmulatorPluginabout/Creatingthejobs

AndroidEmulatorplugin/InstallingandconfiguringJenkinsAndroidproject

creating/CreatingtheAndroidprojectpackage,exploring/Packageexplorertestcase,creating/Creatingatestcase

Page 412: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

testannotations/Testannotationstests,running/Runningtheteststests,debugging/Debuggingtests

AndroidSDKperformancetests/PerformancetestsinAndroidSDK

AndroidStudiosupport,forsystemtests/AndroidStudioandotherIDEsupporttests,running/RunningalltestsfromAndroidStudio

AndroidTestCasebaseclassabout/TheAndroidTestCasebaseclassassertActivityRequiresPermission()method/TheassertActivityRequiresPermission()methodassertWritingContentUriRequiresPermission()method/TheassertWritingContentUriRequiresPermission()method

Androidtestingframeworkabout/Androidtestingframeworkfeatures/Androidtestingframeworkinstrumentationframework/InstrumentationGradle/Gradletesttargets/Testtargets

annotations,testsabout/Testannotations@SmallTest/Testannotations@MediumTest/Testannotations@LargeTest/Testannotations@Smoke/Testannotations@FlakyTest/Testannotations@UIThreadTest/Testannotations@Suppress/Testannotations

AOSPtestsURL/TheBrowserProvidertests

applicationstesting/Testingactivitiesandapplicationsmocking/MockingapplicationsandpreferencesRenamingMockContextclass/TheRenamingMockContextclasscontexts,mocking/Mockingcontexts

Assert-JURL/IntroducingFest

assertActivityRequiresPermission()methodabout/TheassertActivityRequiresPermission()methodpackageNameparameter/DescriptionclassNameparameter/Descriptionpermissionparameter/Descriptionexample/Example

Page 413: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

assertInsertQuery()method/TheBrowserProvidertestsassertions

about/Assertionsindepthcustommessage/Custommessagesstaticimports/StaticimportsassertAssignableFrommethod/EvenmoreassertionsassertContainsRegexmethod/EvenmoreassertionsassertContainsInAnyOrdermethod/EvenmoreassertionsassertContainsInOrdermethod/EvenmoreassertionsassertEmptymethod/EvenmoreassertionsassertEqualsmethod/EvenmoreassertionsassertMatchesRegexmethod/EvenmoreassertionsassertNotContainsRegexmethod/EvenmoreassertionsassertNotEmptymethod/EvenmoreassertionsassertNotMatchesRegexmethod/EvenmoreassertionscheckEqualsAndHashCodeMethodsmethod/Evenmoreassertions

assertLeftAlignedmethod/ViewpropertiesassertOnScreenmethod/ViewpropertiesassertReadingContentUriRequiresPermissionmethod

about/TheassertReadingContentUriRequiresPermissionmethoduri/Descriptionuriparameter/Descriptionpermissionparameter/Descriptionexample/Example

assertRightAlignedmethod/ViewpropertiesassertWritingContentUriRequiresPermission()method

about/Descriptionuriparameter/Descriptionpermissionparameter/Descriptionexample/Example

AVDcreating/CreatingAndroidVirtualDevicesrunning,fromcommandline/RunningAVDsfromthecommandlineheadlessemulator/Headlessemulatorkeyguard,disabling/Disablingthekeyguardservices,cleaningup/Cleaningupprocesses,cleaningup/Cleaningupemulator,terminating/Terminatingtheemulatorspeedingup,withHAXM/SpeedingupyourAVDwithHAXMalternatives/AlternativestotheAVD

AVDManagerabout/CreatingAndroidVirtualDevices

Page 414: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

BBehavior-drivenDevelopment

about/FunctionaloracceptancetestsURL/Functionaloracceptancetests

Behavior-drivenDevelopment(BDD)Given/Given,When,andThenWhen/Given,When,andThenThen/Given,When,andThen

benchmarkingabout/Microbenchmarks

BrowserProvidertests/TheBrowserProvidertestsbuttons,monkey_recorder.py

about/Recordandplayback

Page 415: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

CCalabash

URL/FunctionaloracceptancetestsCaliper

running/RunningCaliperCalipermicrobenchmarks

about/CalipermicrobenchmarksURL/Calipermicrobenchmarkstemperatureconverter,benchmarking/Benchmarkingthetemperatureconverter

codecoverageabout/Codecoverage

commandlinetests,running/Runningtestsfromthecommandline

commandline,options-r/Runningtestsfromthecommandline-e<NAME><VALUE>/Runningtestsfromthecommandline-p<FILE>/Runningtestsfromthecommandline-w/Runningtestsfromthecommandline-eunittrue/Runningspecifictestsbycategory-efunctrue/Runningspecifictestsbycategory-eperftrue/Runningspecifictestsbycategory-esize{small|medium|large}/Runningspecifictestsbycategory-eannotation<annotation-name>/Runningspecifictestsbycategorydebug/Othercommand-lineoptionspackage/Othercommand-lineoptionsclass/Othercommand-lineoptionscoverage/Othercommand-lineoptions

CompatibilityTestSuite(CTS)/Androidunittestscontentproviders

testing/Testingfiles,databases,andcontentproviderscontexts

mocking/Mockingcontextscontinuousintegration

withJenkins/ContinuousintegrationwithJenkinscustommessage

about/Custommessages

Page 416: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

DDalvikDebugMonitorService(DDMS)/UsingtheTraceviewanddmtracedumpplatformtoolsDalvikJITcompiler

about/PerformancetestsDalvikvirtualmachine

about/Testtargets/Testingonthehost’sJVMdatabases

testing/Testingfiles,databases,andcontentprovidersdemonstrationapplication

creating/ThedemonstrationapplicationDependencyInjection(DI)/TestinglocalandremoteservicesDevicePools

about/IntroducingForkdmtracedump

using/UsingtheTraceviewanddmtracedumpplatformtools,Dmtracedumpcommand-linearguments/Dmtracedump

Page 417: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

EEditNumberclass/TheEditNumberclassemulator

tests,running/Runningfromtheemulatorterminating/Terminatingtheemulator

emulatorconfigurationsabout/Additionalemulatorconfigurationsnetworkconditions,simulating/Simulatingnetworkconditions

EspressoURL/TestingwithEspressoused,fortestingoutsidein/TestingwithEspresso

EvaluationDependsOnclass/InstallingRobolectricexceptions

testing/Testingexceptions

Page 418: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

FFest

URL/Staticimportsabout/IntroducingFest

filestesting/Testingfiles,databases,andcontentproviders

FitNesseURL/Functionaloracceptancetests,FitNesseabout/FitNesserunning,fromcommandline/RunningFitNessefromthecommandlineTemperatureConverterTestssubwiki,creating/CreatingaTemperatureConverterTestssubwikitestsystems/Addingthesupportingtestclasses

fittestsystem/AddingthesupportingtestclassesFork

about/IntroducingForkfunctionality,adding

about/Addingfunctionalitytemperatureconversion/TemperatureconversionEditNumberclass/TheEditNumberclassTemperatureConverterunittests/TheTemperatureConverterunittestsEditNumbertests/TheEditNumbertestsTemperatureChangeWatcherclass/TheTemperatureChangeWatcherclassTemperatureConvertertests/MoreTemperatureConvertertestsInputFiltertests/TheInputFiltertests

functionaloracceptancetestsabout/Functionaloracceptancetestsexample/Testcasescenario

functionaltestingabout/Testscriptingwithmonkeyrunner

Page 419: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

GGit

about/Git–thefastversioncontrolsystemlocalGitrepository,creating/CreatingalocalGitrepository

Gitplugin/InstallingandconfiguringJenkinsGiven-When-Thenvocabulary/GivWenZenGivWenZen

about/GivWenZenURL/GivWenZenwikiURL/GivWenZentestscenario,creating/Creatingthetestscenario

GoogleGradlepluginURL/Instrumentation

GradleURL/AndroidStudioandotherIDEsupport,BuildingAndroidapplicationsmanuallyusingGradleabout/Gradle,BuildingAndroidapplicationsmanuallyusingGradleused,forrunningtests/RunningtestsusingGradlecustomannotation,creating/Creatingacustomannotationperformancetests,running/Runningperformancetestsdryrun,oftests/Dryrunused,forbuildingAndroidapplicationsmanually/BuildingAndroidapplicationsmanuallyusingGradletasks/BuildingAndroidapplicationsmanuallyusingGradle

GradleJacocopluginURL/Generatingcodecoverageanalysisreport

Gradleplugin/InstallingandconfiguringJenkinsGraphViz

URL/Dmtracedump

Page 420: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

HHAXM

AVD,speedingupwith/SpeedingupyourAVDwithHAXMheadlessemulator/Headlessemulator

Page 421: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Iinstrumentation

about/InstrumentationActivityMonitorinnerclass/TheActivityMonitorinnerclass

instrumentationframeworkabout/Instrumentation

InstrumentationTestCaseclassabout/TheInstrumentationTestCaseclasslaunchActivitymethod/ThelaunchActivityandlaunchActivityWithIntentmethodslaunchActivityWithIntentmethod/ThelaunchActivityandlaunchActivityWithIntentmethodssendKeysmethod/ThesendKeysandsendRepeatedKeysmethodssendRepeatedKeysmethod/ThesendKeysandsendRepeatedKeysmethodsrunTestOnUiThreadhelpermethod/TherunTestOnUiThreadhelpermethod

integrationtestsabout/IntegrationtestsUItests/UItests

IsolatedContextclassabout/TheIsolatedContextclass

Page 422: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

JJacoco

URL/Why,what,how,andwhentotest?about/Jacocofeaturesfeatures/Jacocofeatures

Jacococoveragereportabout/Generatingcodecoverageanalysisreport

Javatestingframeworkabout/Javatestingframework

jbehaveabout/FunctionaloracceptancetestsURL/Functionaloracceptancetests

Jenkinsabout/ContinuousintegrationwithJenkinsinstalling/InstallingandconfiguringJenkinsconfiguring/InstallingandconfiguringJenkinsURL/InstallingandconfiguringJenkinsjobs,creating/CreatingthejobsAndroidtestresults,obtaining/ObtainingAndroidtestresults

JUnitplugin/InstallingandconfiguringJenkinsJython

URL/Testscriptingwithmonkeyrunner

Page 423: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Kkeyguard

disabling/Disablingthekeyguard

Page 424: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

LLaunchPerformanceBaseinstrumentation

creating/CreatingtheLaunchPerformanceBaseinstrumentationlibraries

using/Usinglibrariesintestprojectslocalandremoteservices

testing/Testinglocalandremoteservices

Page 425: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Mmacrobenchmarks/Microbenchmarksmemoryusage

testingfor/Testingformemoryusagemicrobenchmarks

about/MicrobenchmarksCaliper/Calipermicrobenchmarks

MockContentResolverclassabout/TheMockContentResolverclass

MockContextclassabout/AnoverviewofMockContext

MockitoURL/Extensiveuseofmockobjectsabout/Extensiveuseofmockobjectsbenefits/Extensiveuseofmockobjectsusageexample/Mockitousageexample

mockobjectsabout/Mockobjects,Mockobjectsreferencelink/MockobjectsMockContextclass/AnoverviewofMockContextIsolatedContextclass/TheIsolatedContextclassalternateroute,providingtofile/Alternateroutetofileanddatabaseoperationsalternateroute,providingtodatabaseoperations/AlternateroutetofileanddatabaseoperationsMockContentResolverclass/TheMockContentResolverclassusing/Extensiveuseofmockobjectslibraries,importing/ImportinglibrariesMockitousageexample/MockitousageexampleEditNumberfiltertests/TheEditNumberfiltertests

monkeyapplicationrunning/RunningmonkeyURL/Runningmonkeyclient-servermonkey/Theclient-servermonkey

monkeyrunnertoolused,fortestscriptingwith/Testscriptingwithmonkeyrunnerfeatures/Testscriptingwithmonkeyrunnertestscreenshots,obtaining/Gettingtestscreenshotsrecord/Recordandplaybackplayback/Recordandplayback

MoreAssertsclassabout/Evenmoreassertions

Page 426: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Nnetworkconditions

simulating/Simulatingnetworkconditions

Page 427: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Ooptions,forlatency

about/Simulatingnetworkconditionsoptions,fornetworkspeed

about/Simulatingnetworkconditionsoptions,NewItemscreen

about/Creatingthejobs

Page 428: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Pparsers,testing

about/TestingparsersAndroidassets/Androidassets

parsertestabout/Theparsertest

performancetestsabout/Performancetests

performancetests,AndroidSDKabout/PerformancetestsinAndroidSDKlaunching/LaunchingtheperformancetestLaunchPerformanceBaseinstrumentation/CreatingtheLaunchPerformanceBaseinstrumentationTemperatureConverterActivityLaunchPerformanceclass,creating/CreatingtheTemperatureConverterActivityLaunchPerformanceclassrunning/Runningthetests

preferencesmocking/Mockingapplicationsandpreferences

ProviderTestCase2<T>classabout/TheProviderTestCase2<T>classconstructor/Theconstructorexample/Anexample

Page 429: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Rregressiontesting/Testscriptingwithmonkeyrunnerregularexpressions

referencelink/EvenmoreassertionsRenamingMockContextclass/TheRenamingMockContextclassRenamingMockContextmethod/MockingcontextsRobolectric

about/IntroducingRobolectricURL/IntroducingRobolectricinstalling/InstallingRobolectricresources,adding/Addingresourcestests,writing/Writingsometestsshadows/Google’smarchonshadows

Robotiumabout/IntroducingRobotiumURL/IntroducingRobotiumadding,toproject/AddingRobotiumtestcases,creating/Creatingthetestcases

Page 430: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

SSCM

about/Git–thefastversioncontrolsystemServiceTestCase<T>class

about/TheServiceTestCase<T>constructor/Theconstructor

setContext()method/MockingcontextssetUp()method

about/ThesetUp()method/TestingactivitiesSetUppages/Creatingthetestscenarioslimtestsystem/AddingthesupportingtestclassesSpoon

about/IntroducingSpoonURL/IntroducingSpoon

staticimportsabout/Staticimports

systemtestsabout/Systemteststypes/SystemtestsAndroidStudiosupport/AndroidStudioandotherIDEsupportotherIDEsupport/AndroidStudioandotherIDEsupport

Page 431: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

TTDD

about/GettingstartedwithTDDadvantages/GettingstartedwithTDD,AdvantagesofTDDtestcase,writing/Writingatestcasetests,running/Runningalltestscode,refactoring/Refactoringthecoderequisites/Understandingtherequirements

tearDown()methodabout/ThetearDown()method

TemperatureChangeWatcherclass/TheTemperatureChangeWatcherclasstemperatureconverter

benchmarking/BenchmarkingthetemperatureconverterTemperatureConverterActivityLaunchPerformanceclass

creating/CreatingtheTemperatureConverterActivityLaunchPerformanceclassTemperatureConverterActivityTestsclass

creating/CreatingtheTemperatureConverterActivityTestsclassfixture,creating/Creatingthefixtureuserinterface,creating/Creatingtheuserinterfaceuserinterfacecomponentsexistence,testing/TestingtheexistenceoftheuserinterfacecomponentsIDs,defining/GettingtheIDsdefinedtestrequisites,translating/Translatingrequirementstotestsscreenlayout/Screenlayout

temperatureconverterapplicationcreating/Creatingasampleproject–thetemperatureconverter,Creatingtheprojectrequisites/Listofrequirementsuserinterfaceconceptdesign/UserinterfaceconceptdesignJavamodule,creating/CreatingaJavamoduleviewing/Viewingourfinalapplication

TemperatureConverterclass/TheTemperatureConverterunittestsTemperatureConvertercodecoverage

about/Temperatureconvertercodecoveragecodecoverageanalysisreport,generating/Generatingcodecoverageanalysisreportexceptions,covering/Coveringtheexceptions

TemperatureConverterTestssubwikicreating/CreatingaTemperatureConverterTestssubwikichildpages,adding/Addingchildpagestothesubwikiacceptancetestfixture,adding/Addingtheacceptancetestfixturesupportingtestclasses,adding/Addingthesupportingtestclasses

testAccessAnotherAppsPrivateDataIsNotPossible()method/Androidunittests

Page 432: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

testcasecreating/Creatingatestcase

TestCasebaseclassabout/TheTestCasebaseclassdefaultconstructor/Thedefaultconstructorconstructor,naming/ThegivennameconstructorsetName()method/ThesetName()method

testcases,Robotiumcreating/CreatingthetestcasestestFahrenheitToCelsiusConversion()test/ThetestFahrenheitToCelsiusConversion()testtesting,betweenactivities/TestingbetweenActivities

testHasDefaultBookmarks()method/TheBrowserProvidertestsTestHistory/Addingthesupportingtestclassestesting,onJVM

about/Testingonthehost’sJVMperformancegain,comparing/ComparingtheperformancegainAndroid,adding/AddingAndroidtothepicture

testingtacticscodecoverage/CodecoverageTemperatureConvertercodecoverage/TemperatureconvertercodecoverageRobotium/IntroducingRobotiumtest,runningonJVM/Testingonthehost’sJVMRobolectric/IntroducingRobolectricFest/IntroducingFestSpoon/IntroducingSpoonFork/IntroducingFork

testPartialFirstTitleWord()method/TheBrowserProviderteststestrequisites,translating

emptyfields/EmptyfieldsViewproperties/Viewproperties

testsadvantages/Why,what,how,andwhentotest?considerations/Whattotesttypes/Typesoftestsrunning/Runningthetestsrunning,fromAndroidStudio/RunningalltestsfromAndroidStudiosingletestcase,runningfromASide/RunningasingletestcasefromyourIDErunning,fromemulator/Runningfromtheemulatorrunning,fromcommandline/Runningtestsfromthecommandlinealltests,running/Runningalltestsrunning,fromspecifictestcase/Runningtestsfromaspecifictestcasespecifictest,runningbyname/Runningaspecifictestbynamespecifictests,runningbycategory/Runningspecifictestsbycategory

Page 433: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

running,Gradleused/RunningtestsusingGradledebugging/Debuggingtests

tests,considerationsactivitylifecycleevents/Activitylifecycleeventsdatabaseandfilesystemoperations/Databaseandfilesystemoperationsphysicalcharacteristics,ofdevice/Physicalcharacteristicsofthedevice

tests,typesunittests/Unittestsintegrationtests/Integrationtestsfunctionaloracceptancetests/Functionaloracceptancetestsperformancetests/Performancetestssystemtests/Systemtests

TestSuiteBuilder.FailedToCreateTestsclassabout/TheTestSuiteBuilder.FailedToCreateTestsclass

testsystems,FitNessefit/Addingthesupportingtestclassesslim/AddingthesupportingtestclassesURL/Addingthesupportingtestclasses

testtargetsabout/Testtargets

TextWatcherabout/TheTemperatureChangeWatcherclass

timingloggerabout/Timinglogger

touchmode,AndroidUIreferencelink/ThesetUpmethod

TouchUtilsclassabout/TheTouchUtilsclass

Traceviewusing/UsingtheTraceviewanddmtracedumpplatformtools

Page 434: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

UUItests

about/UItestsunittests

about/UnittestssetUp()method/ThesetUp()methodtearDown()method/ThetearDown()methodexecution,outsideoftestmethod/Outsidethetestmethodexecution,insideoftestmethod/Insidethetestmethodassert*methods/Insidethetestmethodmockobjects/Mockobjects

Page 435: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

VVCS

about/Git–thefastversioncontrolsystemViewassertions

about/Viewassertionsreferencelink/ViewassertionsassertBaselineAlignedmethod/ViewassertionsassertBottomAlignedmethod/ViewassertionsassertGroupContainsmethod/ViewassertionsassertGroupIntegritymethod/ViewassertionsassertGroupNotContainsmethod/ViewassertionsassertHasScreenCoordinatesmethod/ViewassertionsassertHorizontalCenterAlignedmethod/ViewassertionsassertLeftAlignedmethod/ViewassertionsassertOffScreenAbovemethod/ViewassertionsassertOffScreenBelowmethod/ViewassertionsassertOnScreenmethod/ViewassertionsassertRightAlignedmethod/ViewassertionsassertTopAlignedmethod/ViewassertionsassertVerticalCenterAlignedmethod/Viewassertions

viewstesting,inisolation/Testingviewsinisolation

Page 436: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

Wwiki

URL/CreatingaTemperatureConverterTestssubwiki

Page 437: Learning Android Application Testing Related/PDFs and Books... · 2016. 5. 31. · Java testing framework Android testing framework Instrumentation Gradle Test targets Creating the

YYeOldeLoggemethod

about/YeOldeLoggemethod