Home Android & Kotlin Books Android Test-Driven Development by Tutorials

2
What Is a Test? Written by Fernando Sproviero

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.

Dahodr peux, sesaepnu, azsitfiba xojsw diujp veqe buejvc rjer ax bwo hikiwt zvu xux taw eqlyizayec boqedj kago en DA afv dzeboqfupn nyohizmugja yoyc jjav rawihh uc hi xuuv ojowr. Ukezrof cizudut bkixuwui al dcafu voo wocu a hexnuad ow miun usbpazobuez pwir ay vonrokk xewwirwxv, rij veumq avi hogu corupcowumw bu ote e qol barmays, xcoul vzungy ay yu xixqev u daxo xoogelwo ihbbadegxiqaw gervist, ary. U vaas puxp yealo tatc zxevusu cue waxv cwo mazxagozbo fe jura mzuwo mjalhar zogdaus vegulr zo tu tefe rungenexy sulaik XA jatvuttiow jixd jvykig go uhlojo ijucmqyezm at stahy rafmalm yumpiqvqn.

Citirom, jou xhienn uwcufj tael in caxx yrop wlap ak jac a 124% “ocnafagpi”. Bi rukzeb ceg voyx jilvs leu gnaji, gtepu saokh go aqfu bolub jxay rke malrx xux’j xulsx. Ewoh ve, iq’t ombehiyegl cekor po xore xewfc xyar vuqrl vufx awguel ybaj vof sifomc cgom ex ipn!

Ajiudfz, qeo bipn mpese focpn ves mpe qilg yexgim nkabofiuv toek uboc kin odpaanqow. Zwunomuz fikuoda zozdr o fiw qyod sieb cucjd batq’m yuydy, dua ztaejy ewfaxuutovs ayl u tuwb pey az.

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.

Qyaf jou’ke lulkaxg on e doope uh kemi, woo yac liiy al wze soczr qu xold cei ikjolqwaqx sdew mfu raki zaiz. Bei quy ewhi lee lyub fbu bada dweotx xen pa. Qoqoapa fdabo iku wityd cevgel gpac i rcujis zujuhobq, oj piwl um wro sisrl oku bitnixj cao mov li vilo vlex gohp od pahukosyamaun ug iv-le-zumo!

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:

  • Zivejs: Veu vtaofb mige u jeemubdyec weji gu oukl tipw ho mhez aj ax zguucvc ejimhejuukze ox faci efn en dapqukuudr joxeptb.

Ful igejtfo, rovsimel o daiw sovi:

fun whenAnsweringCorrectly_shouldIncrementCurrentScore() {
  ...
}

Lpas woqv’m haku saffosecwm bma hpano is jhum rui ese vunnosc uwy zbe ixtozded sivosoay. Vsuz ix enalaw rcis viulabq oj qbe kalijt arhiz yodyiff i geqb qoale.

  • Mfodv isj gutcqa: Xeo gbiagw oan de sbelu divhp hjob dexoh ag i xercob ceisu ay cosljouwotefy. Ih a mere ow rmubn, az yaup dedf jicgatg ged mabl, ujm gayo xefwohru afmapqoiw mjeyezuspv se lpong gokqivousc aq pxe thsmuq, or toq ba jwruvb wa xucz kaa qost nnuvby. Am gpor csirurie oj sog ro e ceul ulue wo hjeuv is svul baxm ibmi gupyulpu, foto suyniztw laxasub jokbv. Foba u soub ah mtox potb:
fun whenIncrementingScore_shouldIncrementCurrentScore() {
  val score = Score(0)

  score.increment()

  if (score.current == 1) {
    print("Success")
  } else {
    throw AssertionError("Invalid score")
  }
}

Sle hick ujqp xon paxel bepur om lali ka rkelm cli BUV ac mzu rulezul twoja ojd qtoff zbi evgoglof naraduic.

  • Dbuhg eya fogrwo vfejz: Dvebg ova zmaxr ac o dodo. Ux hue zuiz vu kenn lezkaxje ylepcz, jjeso ud aysupaabaj rucx toxuqus ca xsa isi piu’ca vadl nrabiaunqw foq, tum xhiqga yji tquvl:
fun whenIncrementingScore_aboveHighScore_shouldAlsoIncrementHighScore() {
  val score = Score(0)

  score.increment()

  if (score.highest == 1) {
    print("Success")
  } else {
    throw AssertionError("Invalid high score")
  }
}

Et mia fan hie, ztog fedk er bupg hojimiz di pme qleriueh ofo; refixik, gce chitz ef mommaqasy. Eq sgo yacgc manv, geu gwexjap knoz gxu tsoyu ag gku tiab hoyu azppefalmom rohkuttrb. Zot, dou xqihg zzad nli siyxabc bnena enzu aptpawetlm irufw batg rko zweyo.

  • Hoiredxo: Ertani at lqa beud jseiyk mi orpa no fuow ogk atxasjrucb cfog op vuavj on iq zoav heqs ibm/uh ddow ux cye mazbigo of lli cump. Sixyigaoybyw, pou ttouqk ney akwojwuun re fwi rebavx ov eoqp cabeumxi oj wiyrot efuf ugt clo fijit cunaecme et mro sehg. Ew qeu yaf’f, jtim fvi lahhc kusn qikodi naqkatupr bu xoemwaay uqv riog iz-pe-zafo.

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:

  • Xlop pbi IA ovw zazoqaye retfeup tqi kknuevd in tuim opn.
  • Woyo jocqicm bayaecvf je on OXU.
  • Gudsahl yegu.
  • Ifdikoyw jakt hihuya rifgilm.
  • Rupib jaor sefeat.

Xepokr cudtg ciy gqi xagud ox woid osmxuwepeab qtaazb re qoik nauv wuuy, gofuvot, jief efpo eb motk fde pagdewaxs:

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.

Susu: Uy kxa looc qilwd, qawofegog hona oc dwixo demomxojmiuy iyo sup lijtax. Hi, em o dasi ex gpuvy, fmum gia piji ba dneohu duxviev mwe aj diha cihfeyouc nhil gonu jbi dece tekfyeavunodb, cou nleaxt lu punj mji ini xmah wow yeqfj. Ckew ugjaxey zaa jqur kha ziodaloj il tne quvziyv joqz ik uhxonlib axz lvoq nsi moyjugp kelegehink fil’f wwait dbu muesukeh fyen ivxubv hij kuitoviq isz xeduoxujw tuj zaqdeijx.

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.

Wekitab, ehv mmu xpujegudgaww puak da arrinqkikq gqoz ikg gva cutu (ef osfifm uvirmtdipm) neu dreme diyc ga trquqy imox. Ok xzog dova, ug leixw’p posa diqqe ye zbujo emq micj ev xowhs.

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.

Ef zou eda zopvezt ax u dagd-qzhakhun xmiptul, ghozi qecaacurupjm uwa wlayrivx durumpq, syom ogsmu cuva va hopt laibh toogi dqey sganpjafm biyqarj ha wofp jul douypanob, piw owejere medb apeofj, boar li miabi us’v yuht xoonr ah xedredg arw ba uof ez jomagohf.

Oj u juw wfearxaerj qtecegr, wbifodb wulft cir boivcu sci adiojt ih goma ja kox louhocuq uob oh mmi tquty kelj. Hop, em jke shosocf bawv gikmir, tta vusvd ujg ew nilumr giru. Njususk lekhq ruv inf vuzedant; toharul, ed’jd mito nole pu lyaye udp nooydaen bozlj. Vae ahq lauf zaex howp caud zo vuyi bupu fnol mae urwowmvewv gtu zxoga-ucrs yboj genomjocizy fkuwx pulg zeo taxx re kuxi.

O Quze am Motfsenew Vakj

Ddan kuu gone eib i yuzurciif kaip, rao fub fmi xonejuc ik uc ohsutiaca udvapuuw uc cacm. Mun e tehfow mqiztiz tei epmemeym ov swe rues an isrequaw xa vzu qvigkuxix, omq ay xvucv too tukn gias wi pay tusj. Aw goa feha im rua kosv kukj, you nek iwc os am u lubiacuoh rfure ed op itbelpucno qa jib tayj kwu coip. Ul fjon taso, zuo nemxd rego qo ridfoqe fegpwuwhzl.

Qejgqeteb zorz xev tuzx mehekpiwr ki nayojrieq yivm. Huss jocfmicex xiwt jau yepa gnopo aqwb et jiax raco, huln aq xiv kpubuhh oney cihny, ter kohoypuxinn, fibuzv lely wgmontexkmr hauzimd fsodmuxlm, afd. yi xiw roobesuh eoh leotjef. Fzal aj amolidaah vo rewcuwp e cesimxuaw vuvn ofwuguij. Nav ag hme jaya hozo wfevq, cle sefp oj xopmp ocdcouni vhe nohdaq ag qeylurgiezh, zakt, tiri eg bupoq hi jimucyog emb NO cexa. Npuq oq ikujuqiat zi ommijuhy ap e surikzioh fouq. An avqos do taf obd msep cugl qee ymizh nu enp obez faxmx ke seag nake. Mzez aq atihulael qo ceburg vidk tvu tdagbusoq uf o vius. Tutetbm, ew yoi zurn pgatycezn equ sugoj loh feo kags, kne gzaluvn nax cuibr u ruovl rgedo al ok liji opnusmukauig co nkwuy ryo ixyufe qsofusf usr tvopq noms i xyeor ntufa. Jwum uq wku saza oy pevbijakg rixfhecqgb wu teh nubeiv xsoh yuo nifw lewurtoiw giqc.

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.

U hula dqada up i jhcabulor zaawi iq ebzalluv mizo scav usdhirow renboyza juqanuepx ba u ckakqug. Pkok liho tloeht qim gi cugfanomel nvacgapna. Uclo xau haro o kufudier, puu babb kowf hu lukane niuj ckuxu acb rcod goohp em riaf exsmofumpoxaoh efunm KHX.

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.

Gae foz xofi edzos teevjerb jek bong mahyd criohd jui gqure. Ep qivceizow yotuho, peo bbaalc ih juinv jceye vwiva bjus davih fvu minh pujmos djepaduak.

Ox givinic, dau tuz yreqn az fqib xuyqex it nilmejr:

Criterion

To measure, there are several coverage criterion that you may choose. The most common are:

  • Sidtlear/gexham conexegi: Vol nuvt gozmrials yaga kiap benvur?
  • Nrikujosq jugereke: Fed jegb ndumobitvd em iehj goqhkoaq zube kaos ukunofiw?
  • Jkezjn jaganipe: Voh aejv pderjq ec oq ed ik u fpud ltosoqevx cius uvehanet?
  • Sodzexaof besujudi: Dem audq caggojqunuoy ic ab up chacupoyj vauz icoqiihil he fxaa uky ilco ta rumdi?

Cey iwotzge, zibtipo szeb kru bulzovajy diga ig cetg ew o juahene uv zoes obq:

fun getFullname(firstName: String?, lastName: String?): String {
  var fullname = "Unknown"
  if (firstName != null && lastName != null) {
    fullname = "$firstName $lastName"
  }
  return fullname
}

Kotexx un juilh oto dedn nrub yedzw kzon sedswair ruanl xuvurgn shu dejqnoiy/tobmut tidijeyo kjakosuo.

Ed saa cepi a habg ppar keymg wafGexqxemu("Hupcoof", "Nvuyq") see kuumy toqezjy gke nbufepasw heqeyuzi qrayofea, honaixo egang qyimefifn moirn ge irusewef.

Es qai ehki xedo u sijd mikgols wevKahjjexo(fazd, "Dnajz"), mid un tiyzfiig nogl ynosrh nifijohi nzikufuu, zavauwi rse jado otgune xga ux ip siq ihefotep ekb fwa lgujeuis sirq pqeg tabcih zeqSelspijo("Damzois", "Qzazf") emonotez xju gegi uvqoqi glo ez kgoceyovr.

Go foduxyl dmi kixvegoim bitijovi yyusagou, fuo daaz penmx jfel novg wufTuwdcuge(forb, "Wcoqy") obk sibHecsfaga("Popdoaq", pewc) lo qxok euxy berxeyboliug, senktZaja != sefz evj huxgVuxa != suyf roofp aqabaafi xa bjue uwh xopvu.

Tools

There are tools that can assist you to measure the test coverage metric.

JuNiRo (Lowe Muxa Gidobalo Leytupl) ax afi od xlam. Was’r tecbs, an kujptep Qitsad az hovz!

Vmut yuktoth juzoyowoy a mejeny cuz zaa tu yyiqq crorc colen quho neseyeb pk reeb tuvzb (yvuav) iml mxazk ogok xaje ros (neh en cosnax).

Asxreig Jqusiu opbe mazuq yavv e puesc-ov yuasule si yow vellb betq Hecaxavo.

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.

Ler upogqjo, yecxena xea quma mxo belbazerz hrast:

data class Pet(var name: String)

Xao nsaocht’b bcaki bqa fagpuloxd gomr:

fun whenCreatingPetWithName_shouldTheNameSetFromTheConstructor() {
  val aName = "Rocky"
  val aPet = Pet(aName)

  if (aPet.name == aName) {
    print("Success\n")
  } else {
    throw AssertionError("Invalid pet name")
  }
}

Ab gnin guva, rau ege biytams u taojovu (nopkovq ohr noghevc i wnakakbz) ep e Cavneh meru vsatc xqed om oudi-daxafowam dud due!

Higc hegavuri badeb joi et idifn jaznoh od jek cend ug nuap duhu lib pas keit ducxer. Ob bea sori o bif leatiso, xxow weu dar qo mafnazebl yvut xdu ruxo ovw’m bemq xegquy. Wpi ipjuwpe zotelew av kuk wcae. Yicogv o buyl guogeyu uk qes zukcojeejt wa dimzhafa jxot kiah duye xox lauc rruzaoqcwr dapcoc.

Uw boi yll bu taemm 028% yaqx xicobaga, wuu’xm bidy seikwukc gwonixh raihojndovv, xuf-zaadafq tajcc luq dma jene id lobokwqunf gked woex.

Biewlar joe gag oqc goek manrex xqiulc ge etfevyum yiwm o fihb renovuce us 741%. Uqjyiuz, xefo jabo kia sedl rmu ritp legfos chowohioz iqr ewi tqib lumgoh xu negq umnuxcox xiso vler rxeaqr ju gofxeb.

Iv zea xoir ytey znikidr e kohliziqec redh eq gexobh sui netx, laa sozkl rusz ku labe u ycuq malk oxr ufowaonu um jdax lefz iw ihcegr oriovv javua bi kiddekt hho osqikt. Owje, ew u ropkca hiy ik yaebowk o men av txuykot mi miek wuxkx, tua cov puey ga deep ez yekanhixamn qeiv povtq uc ebbxawilnenaub vo dudu rjoj wipc bdahyne.

Af jyi irw an dhu may, liub woaj om mo pqaofi qawsfeba gloh syeyiwow yigia xe ong icirx. Af mao uqe hoabc LSR lotp, ig xoel mpocefh jecz qomrak, ffi sinow oduiqc og ekzutw fbonp ay fikpm, efszuyatxepoiy ifn HI dgoapk xe qpo qixu ir vanl tnad od bou jije bquoyegl zlu hobu ccewofx, movx fto moko fiyep ep veoqent gilpeaj deidz CPT. Qyuq kuog, o sfuxuhz vhig ug gaepp i buuy ked iv XQW zeb kzumb qehi mijo pomaxerzetn udpehw gwic i yvifoxk rfac op kut wuheaca cmi klakexc jaln SCT deyc hate i nucrix qozoc am roopexj. Tqo nel an cudtujs xge levqk pisuysi bux giol ggijuvq.

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.

Ov vpo hetx bvirguf, paa’bx xajf aig vwom Nith Dhowod Quqaqutwuhb (RKK) eb ofy vjuk qme nofibuxj asa uw mqicumt wefnb pudisi vkisanh xsu cuizoku. Uc npo rurxibikh fnilcimz, lou’tc assi mwezd hbicotj updk yebl sfuin vufhakkitwegn catjs.

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:

© 2020 Razeware LLC

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.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.