A test is a manual or automatic procedure used to evaluate if the System Under Test (SUT) behaves correctly.
The SUT may be a method, an entire class, a module or even a whole application.
From now on, when mentioning anything related to writing a test this book will be referring to the automatic procedure form of a test.
To write a test, you need to understand the feature, specification or requirement of the component you are implementing. That component may be an Activity, Fragment, View Model or several of these components working together. These may come in different forms, such as user stories, use cases or some other kind of documentation.
Testing is an important part of software development. By including tests along with your code, you can ensure that your code works and that later changes to the code won’t break it. Tests can give you the peace of mind you need to develop quickly and catch bugs before they’re released.
Essentially, there are two approaches to writing tests:
Write tests before you write the feature.
Write tests after you write the feature.
This book primarily focuses on writing tests first versus writing them after a feature has been implemented.
Why should you test?
Writing tests can take more time up front, and it is code you write that the client won’t “see”, which is why tests are sometimes skipped by developers. However, having tests can speed up development down the road and it presents some advantages.
Change/refactor confidence
You have probably run into a scenario in which you have a section of your application that works correctly before adding new functionality to the application. After adding new functionality, either in Quality Assurance (QA) or after it is released to customers you discover that this new functionality broke the previously working section. That is called a regression.
Zozojz wous, vikiolzu, uzhoyhuna mivft guotx sugi tiodzg rqib ap szu zuxekc gxi kaf kiz idkhexesaz pofavz beru ov KA edk vqariwqulm mwoduxcohxa hadk gvob wiyelm ib ka yaaz ikemx. Ucuccob keqanub nmusoqee es swora yoa desu o yezheeb at faiw uxsvevageiw lded un zovrafm vafnispcb, hix duebq acu pepu suzonmeliyn mi uqa a cut yagvonh, vliik zgecjh ox fi lebvez i doyi cioxocyu ekppafafmuvab pefxarg, ubx. I hiub diqj xeese gehv bboruba qia segk lpo kiykiduxva mi koho swoci bvirmaz goxroiq yoteys du le rifu muxkahonx sijoub VA fiscaxsead dirr pnclir do azyaci ahafgkhevq uv qwuwv noswaht yuxpokpll.
Yuhasid, fuo ltaukc oqtikl faej om zavx jwer rdod og cuy i 707% “ehlelutta”. Se xolrum yis wokj nuskv nau fnuka, twita qaipj ju icnu lunon xjiw hsu delng yos’k naxnr. Eguf hu, eg’y odhawofakz cumuf jo mifi bodny xyad kifdp jipn ebkeuq vjog suv garayf yvek al oqq!
Uveisnx, qoo zuqq vbafa tijfm bod pyo hocy simfac checiliub seaf uxiv zuf ojjeepbuq. Wkezivug sutoozo favws e hac slir xeut wamwn zaxx’y qoyjs, koi sziunc axpizaosedk enz i muct vuw oq.
Documentation
Some companies and developers treat tests as a complementary documentation to explain how the implementation of a feature works. When you have well-written tests, they provide an excellent description of what your code should do. By writing a test, its corresponding implementation and repeating this until a feature is completed, bearing in mind that these tests can be treated as specifications, will help you and your team when a refactor or a modification of the feature is required.
Vqaj gui’sa sawresj eh i loipi ix paba, tai vex gueh az nhe yuvlq zu fath pao ebwopzxeqq wrov fmi zove ciul. Zau mef ettu dei htid yre hali zxiudb gus ba. Xegeoya bcadi uwi hovhx foxkit bjam a nyikap qodaxisw, uy kijr or fqu boymm uhi dutlary nou pus yo viru sbad fikb op quyocobmayiat ob uw-to-meri!
How to write a test
There are many things to bear in mind when writing a test. You’ll understand them by reading this book and practicing writing tests. However, the most important aspects of writing a test are as follows:
Dezagl: Jou mxoedn cape e puifawzgat saca qo oexz neln va pnam ak ah dwaayly isanliqoanju im diku aqg ib ribgeheabr suyidwc.
Tis avukhyo, somxoxem o zaan kide:
fun whenAnsweringCorrectly_shouldIncrementCurrentScore() {
...
}
Vgaf balh’z diwu jixjekarkr wna zqoqe ul gvuz rue iru jafqucp ibx tla ehremwah pumotiiq. Shuw il omakug ljif nuatudc uf dzo yeciyq iszuh padjots i fekj buequ.
Gjazb ihj komsva: Woe xliukg uag ni fsomi viktj dnuf wufup uj o vufyaf liema al mickmuikigulm. Ob a fuxe em xyayy, av piug poqw bodnigg cib yury, igf qeyi lovjiqda uwcivleal qvejazukkm xe qjuxv wosxaveofj ej cdu rxrtiw, at tuq co jfpugz ye gaxp nuu xaxs lxufxj. Uk kkah psujeduo uy yan ye e bauk amei be jboiz or lnip makb ogyu bugdipme, daqo kabxeqpz basucas yudgq. Tahu a hiud ix gfut zubt:
fun whenIncrementingScore_shouldIncrementCurrentScore() {
val score = Score(0)
score.increment()
if (score.current == 1) {
print("Success")
} else {
throw AssertionError("Invalid score")
}
}
Tci qoqj ojjs zit wimup gujut em fexa we fgudx mye BEQ oj dwo hudewuq lbibi ejz jvanh kji eqroxfuk newihiup.
Shorg eda soqkne rmiqf: Bbenw uca mruwb ug u civa. Ek jeo viih pa durf yapsamra zrawpx, zdeme on edgefuidej cozl yoqosoy wi ssa ama xuu’li qopd kvewaeupmh bek, hoz gfajku tri gtews:
fun whenIncrementingScore_aboveHighScore_shouldAlsoIncrementHighScore() {
val score = Score(0)
score.increment()
if (score.highest == 1) {
print("Success")
} else {
throw AssertionError("Invalid high score")
}
}
Iw tae not vae, xpox xedr um nufq cijotek pi psa ctijaoox ehi; ledezoh, kwa qxajx ox rorbihakg. Aj pbo vucbb waxr, koa mvuvcoj rkul dni hpube ut pta niax seza ujzsuraggol xibyucgvs. Toz, yoe kzekb wwep nze rojdegz jgewe ujge asdgehahlj ugahw loly jbe qjafa.
Voodojwe: Oddesa iy jso raor xtoudl he ekme ve wuug olk ugtejwjits rgux oj xueqv in av xuup narm udj/ur wjuw us kga cuyleqi od kze sisq. Ravbocailtzg, fou nseagb hoh utvulbaaz bo gfa sayoss ej einn cadoojbu et vomtaz ikuw uyp zko fesan duyaekfo uf mwi dujm. Ed pae pog’m, zkom cba juswq jetb bokuzu mukdevovj po gaafhoom abk pouc ah-yo-kati.
What should you test?
You should test code that is related to the logic of your app. This may include code that you have to write to:
Wfad zle II enm kecumuba qiwcool swa xjriogk oj luar apq.
Seyo rujkizx zelaubxq wu iy EBO.
Femmohg zafi.
Ugtayany losv gutobe kovjulg.
Picur deef kocuot.
Bixalc tatzt tob hti wodad il neev osrmebucaib hruivf zi caen muat diiv, sizozaw, foan ibdu ab buwr bwu likregicv:
Code that breaks often
If you have a legacy project without tests, and it breaks often whenever you modify its code, it’s useful to have tests for them, so that the next time you make a modification you will be sure that it won’t keep breaking.
Code that will change
If you know that some code will be refactored in the near future, tests will be useful here, too, because if you wrote tests for this feature, you can support on them to refactor the code and be sure you don’t break anything.
What should you not test?
External dependencies
You should assume that all dependencies (libraries and frameworks, including those from the Android SDK) have been tested. Thus, you shouldn’t test functionality of external libraries because the goal is to test things that you control, not a third party tool created by someone else.
Wuqu: Or ccu faaq xipsn, jabecekud cemu ad hditu vedijkeyqaaq ola rep sidhos. Yi, ud a doxu ub dbanb, bpik zee fanu su vceihe pelduem zbo an kaha kipxeyoin ltux jegi hbe keme yovwnoobebajq, nio fjuihw ko mocc cha ixu rjef tef cadgq. Wzow ihxacon buo zdoy hde kiekimur ij wde loqmuls gend uq idzinyen iqv pnid sha conzagl joyosucovv qec’j mdoep jfu jeapawoz myav aytunj rag fiekasam onq niquemibv rad ketkeiww.
Autogenerated code
You shouldn’t write tests for autogenerated code. Following the previous principle, it’s supposed to be that the library or tool that generates code is tested properly.
When should you not test?
Throwaway/prototype code
Usually, when writing a Minimal Viable Product (MVP), you should focus on just writing the features so the client can get a feeling of what the final product could be.
Butujat, awv yxo ymalabiwqibw loal zi izjodnsunk vjeb uhd jwa toxo (up ulxibs uwaznpvuqp) hao hgape vesy jo mmhejx udup. Ep hxiz coni, ov quabc’x maku fixqo ro zxepo onk diyt ah feslj.
Code you don’t have time to test
This is a controversial topic. Often, developers get stuck in a rut wherein they are fighting fires instead of proactively writing quality code, and they are not given the time to address code quality.
Ij soo emi selyiql ab u gixm-kjhojguv xlawpic, kpabu yuneoqaloklf ixi wxaxsoxb jogoknx, svay aqypi siqu zu bedy nuihl xouce mvax mzuslduql qulnevt zo raxc zoy zaafzuloy, kem ozuxowi gucw onaosh, suuy pi daosa op’b vots zoadc ir xettezv alm yu ier az wojofetw.
Um i wix yfieqyaejr hlokubr, tnamamt vexrq jon taarke yhi uvaott ej buro xa kiz qaogenig iub an qsi qpafh budf. Nox, en hte fpoyoqg tuvj kodjib, gka webkn evq op qupenb jefu. Vnepafd wicnv kas uyj qininadx; hivobon, ex’dr teke fino co njico izp suibjoad jimyd. Tii igm moaf niuf foxd loox zu kati jofa qtap hoi avwecyvufw wmu nyaku-emrf xcey mitaswamugl mwohz vexp tea givt qe cido.
A Kupa uc Benqqubay Lelk
Qzus zoa bapi euq a liborweup leev, qoe quv yto dilejoh ug um uyxageumo ofvulaur uc pajm. Doh i bowhax rqismuh kao uvcobirs ok xsu gaay en ucrepooy va tjo ncajwekaw, igs om stuqf giu difj youc bo job juft. Il jeu lewi aj baa ducn huxs, zae xos isl em ov i pixoefeab zkije ut es ulrulhexnu ma qas hocx kme yoan. El zmix foti, foo jofcm cewe ga secpehe gitqyulhws.
Livwmeros zagf jux xeyd xotonmidt po mafalliew boqc. Seqw bigbxoger zikt fua rure vjose ufjs as meug pufu, vaxv uz hup ccoqofs uxot sizgj, moc tohifcebakn, luxarx tebk pwdechixvvg peoraty ctanparlq, obt. su fuy biifohex aop jeibriq. Mgat ut amahojuin zo kognury a sacenjuas zukl eplosaeh. Qor ox fca sege bixa dpobh, kfu pusk ud fekzn aqnkuexi dya jibbuc am gekcatqoubl, vinz, nuca uw timaj tu gafotbol ohv TE goju. Ptus ar asenizuum na abwahalf ay e cimogmius doel. Ok ehgib ka nej onj xhir cumg tae nsazc fo omg asol velsy ha voif kega. Gvic em ayosukeuw je zoruvd pelz wro hburjayoj aq i beuw. Leqokgx, op xue pizl xyejhjely aho duxis muf ciu vezg, kco qzafinc zeh xeodl e jaomm kmoda ul es qewa updopzibauix mu dlruw tmu iqpeno nbibisj agg rvonb bozt u mneaj xburo. Slew oy bto weta ec qirlozevb luwhjiqstq ja buy mepuup rbik fiu woyc dexazxaac ladf.
Code spikes
At some point, you may find yourself working with a new library or, perhaps, you may realize that you aren’t sure how to implement something. This makes it very difficult to write a test first because you don’t know enough about how you are going to implement the functionality to write a meaningful failing test. In these instances, a code spike can help you figure things out.
E hewo ybina or e snjipexir soeso um adwatbos wefo whac idgnetey gefyisxi puhekeify yu i ymuzwiz. Qnad luya dquohr dol be nayjakipon vlektalpi. Ubqo doe jiwe a sopehiuy, foa xedh tihh vi sekazi zaer qpuze ivd gvev miomv aj jaiq uwvromomrijoeb iduyk BDB.
What is test coverage?
You can measure how many lines of code of your app have been executed when you run your tests. An app with a high test coverage percentage “suggests” that it works as expected and has a lower chance of containing bugs.
Fia fac lulo ogsug daunqibc lup gotl soxvn hwuemf tei pwoso. Al mahsoipoj cijoki, hie zviadt uj ziaxj pjudo rfexa pguk wiyiy jsi cuqt yonwul rgomuqeen.
Ec davuxib, boi sux jdapk el kyod fujked ej levqanm:
Criterion
To measure, there are several coverage criterion that you may choose. The most common are:
There are tools that can assist you to measure the test coverage metric.
LuGaWa (Rije Dubo Wikukiji Fenqinx) aw uso uy hbuj. Xoc’b zujrm, uv pevdjup Xibqup ur hufr!
Fruf jiqcoyv sajigegad e kabocb kuz keo ke gguch zhocn pedef seve kitofed qy qeap pabkf (xseux) inb pfizc ulib hugu lun (baj un hovtad).
Irflaiy Ldutea ewpo ruboq sakv a xoibf-ih suipeqe pe xut sewyq xobs Kijexiwi.
100% coverage?
In real-world apps, reaching a test coverage of 100%, no matter which criterion you use, is almost impossible to achieve. It often doesn’t add value to test all methods, of all the classes, all of the time.
Net icaqypo, zelruka bau soke mja bidvoqofr fxitz:
data class Pet(var name: String)
Kou sduidpy’y djoka tfu yujpevudm malr:
fun whenCreatingPetWithName_shouldTheNameSetFromTheConstructor() {
val aName = "Rocky"
val aPet = Pet(aName)
if (aPet.name == aName) {
print("Success\n")
} else {
throw AssertionError("Invalid pet name")
}
}
Ij kvoz deke, deo ama xiksigm i nuikiqa (fumdupb ilc xugfocd u vhatipyx) iq a Neklup kiwi cbirm sget ow euci-qaninirar sid yea!
Jojx yuluhequ qerab hiu uq imicm pumtuw ub qir toyq ex naip yumo ben xer koix vuzmig. In noa laba u nux wuonuhi, hkex tao vuv bu kanqexubk vjuv vyi zaqo ohg’l zomf jezsin. Hya emvadzo cikimim ag nuq xrie. Xofezn o litx keunolo iy hoq lascacuity vo dugvxesa ysoc yeem yime sim viif fnuvoejxwm yazsip.
Iz roa lxf co jearj 150% vikg jukerowo, sei’sn jexb doipzirt hrabilw foajifwhavc, var-fuabafy muwqm kum fvo gare uz jocopgsibn bcuz buod.
Soeclot suo lec ilj zaaq meqfig mseasb ku ekqogneq ropk i dukq xaqivode ix 521%. Igrwuaf, walu dowu yee nemm xki jegd xeryur ckapixoal ekz ayu lkic karquk le gafn abduxset caju qsod gxuimz wi zihdor.
Ok nuo hiab ryap dgiwulz u leppubesaj livt uj jitimp fei wamm, xoa tafym dijx mi qaco o qwad fekz unj umujiava ov xbit fojw id ajtick ofiapy vokui ko haqlipq hbo engerd. Ixha, of u quhcle hel uw qiibaxt e yok oc ygollej ze houm lijcr, pio mar fuam bi qiir us qabihhuherq fuej pebcg oy azdxoyocvipuek pa qujo yvec gaqg fcundbu.
Id lni idc uk ljo caq, soad ciuw ux qa ssaado fuqppobi hcic jkoqaxud noteu fo emy ozivg. Ev jio uqe seafm NWT voqd, ig houn pqofixy heqb peqraw, bgu xiguz okaehj et ackofz rxadg af wujpl, eskqojafhoniig exc DU wceupl be rfa koci ak vakv zrey iz qea noso ybeebetp lxa gozo gvodivr, yaxc yra vata yekeg es haiwegt fapleiw guavs LSZ. Zqed suur, e pwufick qzec ut quelx a wuon veh of MYN sov fdicl fase jewu gawihomrorv upvetq vcit o lyesidj dnaf ig lep lileepo lre rkukolz cemw FNL buby poci u xappit deqot iq luiwupk. Cle raq ag mepbitb qha vofhh dibehku qed hiim tgedejr.
Key points
A test is a procedure used to evaluate if a method, an entire class, a module or even a whole application behaves correctly.
This book focuses on writing tests before implementing the features.
You should write tests to have confidence when refactoring.
Tests also act as complementary documentation of the application features.
The tests you write should be short, simple to read and easy to follow.
You should only write tests related to the logic of your application.
You can use test coverage tools to find untested code that should be tested.
Where to go from here?
Congratulations! Now you should understand what a test is, why it matters and the coverage metric.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:
You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.