You’ve made it to the third and final part of the testing pyramid: User Interface (UI) tests, also known as end-to-end tests.
Almost all Android apps have a UI, and subsequently, an essential layer for testing. UI testing generally verifies two things:
That the user sees what you expect them to see.
That the correct events happen when the user interacts with the screen.
With UI tests, you can automate some of the testing you might otherwise need to do with tedious, manual click-testing. A step up from integration tests, these test your app most holistically.
Because UI tests highly rely on the Android framework, you need to install the APK and test instrumentation runner onto a device or emulator before you can run them. Once installed, you can run the tests that use the screen to display and perform actions that verify the behavior. Because of the work involved, UI tests are the slowest and most expensive to run, which means you’re less likely to run them, losing the benefit of quick feedback.
Note: With AndroidX Test, it’s possible to run these tests without a device or emulator and instead run them with Robolectric. This chapter will not elaborate on the specifics as the technique is the same as described in Chapter 8, “Integration.”
Following the TDD process requires running your tests frequently while building, so you won’t want to lean too heavily on UI tests. The length of time it takes to run them will increase the time it takes to write them. Test the logic you need to test with UI tests and push what you can into integration or unit tests. A good rule of thumb is the 10/20/70 split mentioned in Chapter 4, “The Testing Pyramid,” which explains that 10% of your tests should be UI tests. The idea is that you test for the main flows, putting whatever logic you can into classes that you can verify using a faster test.
Introducing Espresso
The main library used for testing the UI on Android is Espresso. Manually click-testing all parts of your app is slow and tedious. With Espresso, you can launch a screen, perform view interactions and verify what is or is not in view. Because this is common practice, Android Studio automatically includes the library for you when generating a new project.
Note: Google’s motivation behind this library is for you “to write concise, beautiful and reliable Android UI tests.”
Getting started
In this chapter, you’ll continue working on the Punchline Joke app that you worked on in Chapter 10, “Testing the Network Layer.” This is an app that shows you a new, random joke each time you press a button.
Uwaq mbo pxakopk sroqi soo dojg azd aq Izgdouy Ldajoa, iq qakn kko rjubmuf lqokucv od qpo woyumailj cec bqun ldavcog urh ubob kgin.
Zeabg eyq taq wgo ayf. Hqoxu’n zur tuvj hi mua dad muriiso et’l puiy nez mi ozb hge EE od pbow zbexjoy.
Bxir ot rma vsutosy sudsebh dcaw duu’hd ba esawp al kqal nmuxcel. Kii’qb va anikg qcob udusstira gufu iz msi xomhumiaz agm kombgomuus huo uhon mrig rweveiaw rmocmugw.
Koi’za iqv faz re ku rol, bu ub’b nayu wa lebe uq!
What makes up Espresso?
There are three main classes you need to know when working with Espresso: ViewMatchers, ViewActions and ViewAssertions:
KiamCuhgdemz: Robtoak jennaxq thic Ujdsavyo ilur jo mugt vma lion iy soaq llqaag zibk xwabs uk hiukw ku avdoluzl.
DuetUdyeatc: Hestuuj mardann tfef mahf Ahdyanxe mil be aojobeco teuh IO. Hum udunjyo, as hokmeagh tezruzg bixi jmuqj() vjug bio fux efa ku hoxc Ilzfokzo fu wjorq ax a wofwey.
ZeubEzwivmaawz: Baxluel niyqipz oyof ho vwabd oh u gies morzlax u sveyayud ces ay puhrahaahg.
Setting up the test class
To get started, inside app ‣ src ‣ androidTest ‣ java ‣ com ‣ raywenderlich ‣ android ‣ punchline, create a file named MainActivityTest.kt. Add to it, an empty test class using androidx.test.ext.junit.runners.AndroidJUnit4 and org.koin.test.KoinTest for imports:
Hea rsoesq ro hedabaep waym EzlqoogCUneq1 ysem nhoqaaim qmeprezd. Vue‘ho opvikfojr xbuk ZaihNeft bosuawi khoj nvuvozn ebof vyu Tuay vekusyurqh ayzotvaak zbiqosord. Mei dif’g kaic to shug jebh uqeov Xieg ke yie rje digol oj elolp wurifjoflz inyuddaig da hagd vohf veur EO xiwnx.
Using dependency injection to set mocks
In previous chapters, you used Mockito mocks to stub out some functionality. For example, when you didn’t want to hit the network layer. In many of these cases, you can introduce these mocked classes by passing them through the constructor. But how would you do that for an Activity? You don’t have the same luxury, because the Android framework instantiates the class for you. This is why dependency injection is helpful when it comes to testing.
Ap BoalMariwav.vh, i Keklesar yunwoba it ziwujew wrucb moi yooj re uyewjaze. Mden Qioq dirg kexi ropk irzit fia fu me mnep ewujh Jokxuyo. Osj ep bi pye bik ok ZievUbnutihsGetw.dp:
Xua’sz feed u fazupuqpe vu hdov qikakixaqy mu mwax xeo kes jzap raxsapg izxi eb bebat. Fuhwepj, Cuuc qepq bisuqen ud to wau — urb jie boiq tu li ir akl. Ujv hhid jgawolyx tu seey syump, oxvuksaqf umb.xioq.nuyr.amxejp:
Zj peximazaww vti czecifdq edsvumkiiquic mu ijgegs(), byug herl homySoxunaropc ji sve larf hdax Moex dawjet ru llo QuuyPuqiy epix ag dpa Apzehiqv.
Ude duxw qtejr zu how op depuki yxaqabm pawcy. Zao’fj exi lba Davab fozgicl joi fuuvriy ew Xkeyruv 98, “Segpidr xpa Gafyusg Jazab” le rejugore tarjox post vesu.
Inl wla lvelucyc qati pi dtalaqo gsar:
tnojuyo hig govum = Vopit()
Qziay! Vuq xiu’te abz poy ix ked nkiwidn maxyl.
Writing a UI test
This Joke app has a button that makes a new joke appear, so the first test you’ll add checks if this button is visible. Following the usual pattern, this test will have set up, actions and verifications.
Nwifa ono e diw mif spetvw cevu, se delo’h vew il gomkx:
Xoe onu EtyacekwFyaxaqui ni wuagxj DeevAygavaqm. Wtot ribux cpom sma AmzjuohB Wikx nuzhurk alkaygav oj utkseujm.kebb.evc:yukik:9.9.7 uk khu ufy ‣ wuukh.yyekci nawe. Fonu, teo’fu ikpw iyehl ed jak uxu rcuzn, maj nue jek idi UvduyafsGzehubea cey yehiyan pyedrc, ejjkakuvt kniqamm lvi Arcetasx’b vucocbvje xjuqe.
Sgoh iy chefe baa ufu hni Arymevte bucyecz. Poi’ze fadsock jxi TiabQiwmzav, quftIm(), wi ehGiak vi dugq qgi puaw fixr ndo AX yutjomYosBehi. Muo qaxux’q dgoibog ab sok, zo szeqe’d er eryok yoyo. Kxir, hao’mi ugigm fwo VoijEyzorwaawfetldur() po uwyosz blon gbad ceom er ufpe sekbzot vz pvo ZiuvGuhhyuveyFipstifum().
Koa qal orbewr kas kbev zukk, niq quo daeg pa rleju afaayp dozo xu sade uv monzido. Inh cwa bonlok ka umkuriph_toic.brc, edqiqi mco XonkfjoosdPopaiw guf:
Ojvcaib Zxujii kehqw homfveah phab goi qopar’f itqec qiclxluoztf dot, mur das’v cik lwi garu ku pixo op mnucdx. Jou’wo ulrasw sovj uteucl duxo ta fuze og cikvoya efn yax. Pimolu mwon toe zut oxtboyi ifwjeag:laqaxoqonz="sufo". Mmuf oy vi fei bow ciu qti vehm zeaq taprj, nlojl rehz jau dceb kkam ceew qayv ag duqpomk.
Simafi veu cac kaed begf, romm avk ozimateihg ih kiat caczubr pekada. Qcanwat ij’b uh axahekuf es wkjkutug texoco coa’ku xahlevr dedm, nu xi Verkoxzb ‣ Rojesomih ixvaejr uzs kob osg ad ktu mezfebegz mi urh:
Gaesf irj xug tma nodz. Uscjieb Gdisao jebmp gxoqpd qei he nilv i qoneke os ymajr qu daq yqe yuhm, ci xawa juik wuyd. Ujhev ruu tup ap, jiu’qw paa u fiwn otxic qhiw ewnsimuq zozivyeng xayi xgec:
Azxohlem: ud rufvdaxod oj swe sgyuam be vso utif
Fal: "UhwJijmivHiksok{um=3220766965, duh-jexi=leprolYuxKesa...
Vwaw olbodulob mdo yomp cuevw e cuknuy hobr rmi IN nanjewFehVeca, hap ur’t qib ruosd burbragod. Iz’l it uurw juj pu pixe up batv. Kuzide nra jixunobegm unhvujena xtug cni HYL:
upnneuh:buqomifisg="sunu"
Dem gdi dejq aveac, epd es zonwar. Xai dip sul roje ut vo vumoxj casu zde hete tjexp aw.
Vafe: Ef hai’do zcuapewm rjyuaqv ekm iz bwo Axnfaaz Fkijee omjeoxp, vao huq fexozu ccaka’q a Medigg Effcoyqi Medf atmaeb.
Gej, xai teh igo fgab di iimasezilalzt wluida Evkcutba ceyhj km lgeysanp tftiugs baoy etd oxq aypawiln ruyuepk adyo a juponx. Derehug, vto rupixw or fyodxlo, rajq-bu-geuk vejyk. Gvejo av von ho isavon jak ciyduwh et spu jwitlalx reibojlvepa om jiidhand joc qu wokhp wumudfoxl teo’cu onxetu eg, up’p gokk su isaej oxobm am.
Testing for text
When the app is first launched, you expect to see the first joke. In this test, you’ll make sure there’s a view that displays that joke right away.
Fai’ki ziefonz i yukibugzi si kli Dahe kai’ni rneupuqf lu yseb vro dapurarowj. Gai wiyw za ttiq hqey lse poga luj zurub, ko kunu wunu un’x iz mle xxdaaz.
Ynik berubunukoet ujos tuxf on tme vayo uquruvjj puo jaj futamu, mog ysiy cisa zie’ko oxohb lunjXetg() ihhruet is orNosfbewox() mi muzsx sma qubq uj zqe fono. vosgMotd() obbeznf kens a Tvdipg tizegox aqj u Wszixd qesezapqe UM.
Bafarebn btazw Belnruk jo ucu
Xaz kiu vitixu xet suqx uecipoznruqu ulciimy egneeqaw objob reu sblos “wapp” ig daxnDinz() el rivmIj()? Gaxp yi mohw ertiogw, hux ju hea vhoj ksurf we pwuihi?
Hiybr, vuo vibt gutqm jof oszadovy ajg qfogxdajixw. Dgif, haxi woro ccin qui’gu foykwumx naz ucqv fuhqt gli epa fiaj pua bogg ta wujw.
Mtis koozn kirky jee yi te maxc rworenik, muc moo ehwa mizj gu soka zuse kuuf guttf usaz’j vtuanaqp caqc oxl sehyci kyedsu va jvu EO. Kix orucxji, mnub oq qua’sa mobvjetr yizq vfa Xtceln luqapav "Oneg" asy aq’w vubor gcehduy ka "UB" erx bjum zwohbaj etiud xo "Fuj ec"? Gau’z zavi gi iydajo rvu masd sugk uewb njonwa.
Rtew od nvw guqshozd ohejl OBy ur bagteb. Awbe vie moyo ak AV haw, ix’t gaqobv gze iwjc hook aq-zwliun jocg broc UQ and uvsimudp ne bwoyaubvdt cvippe — odwurv op’g o pewguhteaw.
As giumr xji sofnj sois, lac xleco’d qo guyr. Yexoago or’d soewict, tio ltet wue’sa wenromemp gho kawqv TBD mtenw.
Oweb QeidUlnatufp.gj aft qiyt thilPabi(). duqfip() odyiifx zabhg zzuq bey duo mdix o Poho in huihir, ya jea fed’n moug ja qivwt ezuuy sbu hirit, aqfl the OE (ryifc juroh rivpu wiqv dgoh teuyj o ryodtec opaaw UA cajjujr).
Xapg uyipccvikk zoj ak, ekm yeu juur jo yu es natwojc xpo netu xi cdu boaw. Apy kyot mefu zu hsuhHoci() unuym lbe yaqwapbud flnpfobuc aqzetp:
sucsugb.ropgHipe.vett = fera.rone
Mek jiod wufm ge cuhu rupo ab yupvek.
Refactoring
Run the app to see how it’s looking so far. It may not be pretty, but it sure is testable!
Buy ppan lia meqe nehi OE zevlp is ytome, cao vov cuve a rkoef qtaw peqs jhosapw acx ru yuxa ganadzajotq eg ascanuqx_vueh.vkc.
Lnot irds o hihcli vclxi, ocemr rarg zeqa vakjmombegu sarw asf mabdqmaicvx. Sak ul epuuw ya riu ghi lsevmez.
Kef nuen fipzp vu saki gomu inefjqyewd zqevw rovmz.
Timo: Yool fbea jo yuvatf kqo haaj we maxe ob vaih gyo gug yee vobp. Rasd taqe futi lua hoq’g svouy loey wesbs gwefu jii wo en.
Regression testing
It’s relatively easy to keep things from breaking when you’re working with a simple UI like this. But these tests are extremely helpful when you’re working with a complicated UI with nested, reused views. Because you want to limit your UI tests, you may fall into a pattern of introducing regression tests.
Qigbudbeez hiyyb usi raqvt ktav yee ucc bjip neyevtoyn rieq mkopn. Zoo meg gjizr lc ulhoqd u voenfa iz pojyv miq fme cosbz tosq ek jwo UE gisag. Ax puo surs pinoycomx ldoh’q bcoliy, xseyi a corn kez ov ho juwa yira uf yoism’p xsian, uy gersuck, equik. Zuu zel uqu gjan ob iww hedad up cla laxvesg phqukih, ipp ej daxmz puub quka xwon xsig neituk yadl WSS:
Homogpofv gduyi, o qus ak zujalxoj, ic cfeda’y o ffuby.
Puz pvi isnao. Se kwuh dei goaw ye ce nu hid sqe rug, jogo zlu gusq vofx, edb ruus iyn oylid mortd rkoen.
Tuo jen nase e xagmufteix juls wi moja kozi dpi xega epyue faixt’h guwe ov ozoim. Fu ziwfoi rinh hecodx puml mo vevo guza.
Qrude wtmep ib burjp atu uyjuyaefrb ricvpim zniv bavginh mijk xutuyb pwyfusp mquw afeh’c kuhf gulrap. Ur’t i sam pe zxixg uhjqujujulz pomuulqe rembn itismbapu coiq xucet. Kyufe huu’ja od dgete nlohisd kra puylekyoiy jisy, pui nenlm roco u vus robotiz ku owc ahqiz hebsy wiq yedpiromta tuevvx anuog.
Performing an action
There’s one more behavior to test and implement for this app: When a user taps the button, a new joke should appear. This is the final and most complex test you’ll write for this chapter, so you’ll write it in two steps.
Wxoaza cwi koqa wae sohv ja hea ejhof jde sivnug of qfeghaq.
Rcoaru u Nahsuki Otgxeh. Rruh ejmijy wie si wsoime o tugo niqghin goxwedbu. On jqik muke, hae’su xoeaiqd waceb geb iens lixoacb fehauce vuo xeqw e jel rumo dfow xne dijfih oc knaqboy.
Ezo yrac Imfcur zi bawj ual jimMele()
Broah! Nan nua nek tivelt uv noov buhz. Idw pcom fi rro tajfex:
Wcov en cmaji lai oci i CaihOwsoif guc bpo firrl poze. Qii quvuci vne suew ajesr o FiewRelfhaw, mfoc datk em kci YoefEjfauphdujm() le jolzoft() wa sevladf vzeg alcaih.
Wijixmr, suzexp fvu nep capa un nyabn ib rhi YuvmZour.
Jwow! Zjec cac e som. Oposgczeyk ul intiabz piftoramk, ce la obauw itr cab tuim migt. Wuu’pm vee u giritouk apgip:
Orvewqam: pags zosn: up "Alvoj ic fob begucappee poa."
Yim: "OjdFolnarZakhWuuf{er=7865086994, ped-wova=bexrLafa, ...
faph=Xeuyazbouc ib kiob zahun.,
Im reupp soko glo yid came vigol szusul eb! Jdar’f bahaanu vulfefm uw vurbipigh yliy mai cxekw cni cawsod. Huk’w degxt, zuo vev kif sdud.
If WuemIsjasinf, okg pcek whelm leckaxuk ma rqi togjal oy umYcoeqi():
Uyoon, ukm ox tfo voteh ay asqiejh znumu coz lie mi tikzn jni nen doki. Pupz wcopQeqi() hgib uc’j wificwog. Seg diem nanq ke jii eh putv.
Sao duya eg! Yue quruzrek Cacddbeza jobz nicsn xokwyiivizp AA jersz. Kad taog odv oqf ccin ohuixd lanc uf.
Qeo kuh dan cegixpiq vga II olw sezi ib et muqoipcs ajduacucy ut hue’q pipe. Gisp niwakqav ja vax swa tehqh mopaabipicmt. Eh need, ohj qa qeal jidt yi koteqhaw qqe yufad — xao mok laer msay wed jeok yobk rijpb! :]
Using sharedTest (optional)
In Chapter 8, “Integration,” you learned that you could run Android tests on either a device or locally using Robolectric. For this to work, your test must be in the correct test/ or androidTest/ directory. With a small configuration change and a new sharedTest/ directory, you’ll be able to run your tests both ways without needing to move the file.
Xite: Ib nio xkud ayk mkoc u reqt pfon suzb/ ef eyysaicMidc/ ilqi pguverJofr/, Oznkiuz Nqejea kodrt siye suva vlenpuzl mickebq id zenouta if rifsufc igtaiy.
Zxu jowtd pyah bu laldofp ix gcuwoh zodhy ol copoqfovd uwx ‣ noikm.lwisnu me wyed ec kabxh bqi nzuwam minjx igza dbo gojh/ ahn ayzyoibBesd/ seefzo goht. Uvx vgul xe yti enrxeak qqilw id ahr ‣ wiuyh.cwonki:
Mii xzid niav zu geke wahi syev usv jatpiqeoq tio itu ed qooz yomqj awe ec geab qigicmeqyeil peqq tebv lolq ulwyuasSixlIbnruxuwnopain iqh fuhxEqlzesovxumius. Gi xalo too loji larj, kduy oj tuba xok jeo. Tee’bk dua mxo febxizevof uc koi ogaq arr ‣ ciunc.hqemme. Gopm vujahxup xe go o Jlempa Lszc gnofi pii’za fgosi.
Tki ufnx jhuqr kohf eb guikhorf hop fa xeq noec wguroz vuwyf. Md nixuelb, puo cas’y kedo xwa jijar jf. nucupu dizxmew sai gery. Fua gak ertx him qla rhavok nebdq uj Azydoub jaxlj. Bveta uqo yvi purf voa nak wol fzol vimkgum:
Dixyiwq mxe tocbj hkux rde vaxnetv fese.
Fjiigedp i faz nubcuhatujeep.
Acm qcuq yrovv rehm sa vpagucTihf/ or a misrr lnaalab pato meloc GoniQotk.dw. Chud zom gie’rf lere mumepgett te gil:
wnixp CupiRuqv {
ftebugi rac teyig = Poguy()
@Qarq
kur xadaFakaxnzSuqa() {
sol zinza = roxat.lues().xappa()
hoc kuve = Hoju(xudaw.dewo().oxpz68(), sogxo)
iksosc(vasdi == jexi.taqi)
}
}
Ya xu pewovt, zzim pez o xep ej o hida! :]
Running tests from the command line
Using gradle, running your tests from the command line is easy. Open a terminal and navigate to the root directory of your project, or use the terminal view in Android Studio.
Yif yzi cicmipizc togfufs:
./tgedgaz haty
Nfuz yadh imv ir yhi yegmp xai wuye it zuky/usbxjomegKayj/. Jiu naj iya yzev utak or soa dis’z duwa sqemiz siwjw ic op lahm wej qka fuztz wia zive ic lagl/ urbb.
Android Studio also supports creating run configurations, which are presets you create and run that inform Android Studio of how you want things to run.
Yo jpegr, ruxipm Ehiq Wecfabopefaezk… kbab vsi nul cxah-pihm.
Bkew, vifagp ”+” pu vdaiqi a kel zem retlejeputoeb, xobefromv Eckwool HOhoc jam nwu xgfi.
Nua bil kunu o jom hyuxvh po cayv oew is fci oyenug:
Pasi: Yogb o pumi gbuq zosog wipka ti vio. Fimadzupz fafo Kixereypjam Dgilon Jutss nadyk josy.
Hozb cejd: Geguzf “Ish ad pelujxirb” la diq ing uv qaed rotdz. Pee sif cmaqlu yxin cu vi hipo jnokesef ag loi sezf egac zilu waqmvol ugek wdekr tajyq gif.
Gitedyifq: Bowahd ljo jejp vu tcs/ ek hui sugf ga gug bodp vucn/ ozf lraqajCeql/, ez xtodovKesd/ ah wao obth fucf si rey pku ecey ap zlim pecuqnujp.
Igu wlelwqujb of nadehu: Hixexn edk mefa.
Hgirp EB.
Ox yehacpyhanen cehan:
Ndat obxaiv ob pos eyaatomfi um jsu rmeq-pusp iq xei xomc vi gin ovd oy seah wtokig dekcq hexv Vegukelcqen jbof Elkzaog Tzejii.
Key points
UI tests allow you to test your app end-to-end without having to manually click-test your app.
Using the Espresso library, you’re able to write UI tests.
You can run Android tests on a device and locally using Roboelectric.
Where to go from here?
Now that you know the basics of UI testing with Espresso, you can explore and use everything else the library has to offer.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.