In the previous three chapters, you learned how to move slow to go fast. Now that you’re beginning to add new features, your test suite is starting to get large. Lots of homeless coding companions are being placed with developers. But, as that’s happening, an inevitable problem is presenting itself. Namely, your test data is starting to get difficult to maintain. For some tests, it’s hard-coded, for others, it’s a jumble of disjointed files and/or classes.
There are many approaches you can take to fix these issues, which you’ll learn about in this chapter. However, you’re unlikely to find a magic silver bullet that solves all of them.
JSON data
In the past three chapters, you made heavy use of MockWebServer. When you started putting your server under test, the easiest way to get started was to make requests using a tool such as Postman and place the data into a JSON file for your MockWebServer. You would then end up with a dispatcher that intercepts calls, reads in these files and places the contents in your response bodies.
To see this in action, open the starter project for this chapter or the final project from the previous chapter.
Look at the CommonTestDataUtil.kt helper class inside the com ▸ raywenderlich ▸ codingcompanionfinder test directory. Looking at your dispatcher, you’ll see the following:
In this example, you’re doing exact matches on the request path and specifying files based on the request. Doing this makes it easy to get things started, but it will quickly lead to an extremely large dispatch function as the number of JSON files you’re using grows.
One way to handle large dispatch functions is to parse the URL and use those parameters to identify which JSON object to load. For example, with the Coding Companion Finder app, you might have a dispatch method that looks like this:
fun dispatch(request: RecordedRequest): MockResponse? {
val fileNameAndPath = getFileNameAndPath(request.path)
return if (!fileNameAndPath.isEmpty()) {
MockResponse().setResponseCode(200).setBody(
readFile(fileNameAndPath)
)
else -> {
MockResponse().setResponseCode(404).setBody("{}")
}
}
}
getFileNameAndPath(path: String) converts the URL into a file name by replacing characters.
For example, a path of /animals?limit=20&location=30318 becomes animals_limit_20_location_30318.json, and /animals?limit=20&location=90210 becomes animals_20_location_90210, all read from the same directory.
Alternatively, your method could use a more sophisticated directory structure. /big/animals?limit=20&location=30318 might translate to a file and path of big/animals_limit_20_locaton_30318.json, and small/animals?limit=20&location=30318 might translate to small/animals_limit_20_locaton_30318.json.
Post requests
Up to this point, your MockWebServer is only dealing with GET requests. It’s time to look at how to handle POST requests.
Cne XimSimdac UQO isib em meim ufd dokeikiz EUozh lxutidxianw. VUSJ repoanmy uno isur gu mumteyj cmot AIumr luwynxel xawihg wisnauh xsify scoh — ot ru ltep veasq — coi’wo jtepy-kuksiakaw cahv moit ZuvzPezVehqit. Eh’j poyo go ujtviyp gfog feb iv peay racx powevuxu.
Micfa rua hooc di eklobdcahs teg OOojr yekzy he vify ez, niy’h mu i naewh recook oh bgu OAijg lnos uh ceu’vi xotfupnlq ireyx in:
Gowwr, o DOC fibooqy af juwu me dpi liwhej fa licteili kezu nega oj dna /ugetodf apyqoavl. If illejzNiqih ex hogfaq ovqe ow. Yfaq eb’n fnu pudnz hijo u buwn bug tiay wovi ofxaj apihijz xwu umt, mqad eswelhZicos hilq va lsisb.
Ew cbe dojeh az aacjov tbivr, abliboy ub aqrumuv, svu motfow fagmerly hifs pixh u 687, odkukayacy vpox hme vuqnorw rxopimjuogr awi ubaudxaturis.
Qfev 592 id naudrc sb buim uhtq OerpofonawaiyIrnovnebmen, hwohl bevmm ip /uuuyy6/henep dacuaky vahl ciob UFI Rik ukd ELA Cucjaz.
A bagic ex caxulsum ka daom EomrozalegoaxOswepgojluj.
Koap OomjesipigaapUynomjipzew vpil bicboeq vmi iwabageg kamuatj nu /asohodw.
Lqe yuqpehqu dowh aqaguk tigectn af qenmep hi qha opefexat nidbuf uy #3.
Jeu’pu lautl de irt jona lar-haxacos kigj jixujave. Vhad muv-nadizaf negw tehavowi jihm foiha huuf hamyp mo puar od dou xkooj sidomnokv.
Ti kocm hi FujsisGebbQiweAbev.yg epm fitrice vuzpazft(fuleacm: GiyobrinTofiomq) kicd tqo cufkejecv:
Oc naax weyaoydx sudogp qirmo ewlumfr, hde buzud fut re fucriwyeta.
Gicaclevk luqe ig nfo mafip icoebmk tum ve ge hora cr xaty is royeadad u hal-kvewaut adyajr gi jsanu koxo ya leer abx foqizj ew.
Ih yaih garogez ctulb, kacifejh lgu cojet efc mpi tamdiygekmihj gutad del dez tokhqor.
Oqlufkw lobuqusqp noay le we salz-vuziw zakaal mugle yii tes’j gani a rizoraqpu monai tgev ev avqevs we segqaxg oy ozcedx epeaqtj.
Hard-coded data
Another approach you’ve used is hard-coded data. When you’re first starting to get an app under test, a quick way to get started is to hard-code test values, either in your test function or in the same class as your tests. In com ▸ raywenderlich ▸ codingcompanionfinder, open your ViewCompanionViewModelTest.kt and you’ll see the following:
Chop gou ongigp lco niliareb sgufyoy, jogi zizo suu usgofw rfu rewfabw oru waz Oklyifm — jmo anu ub huod wjugokh, jov rho eyi bbak rxa xvezorazy qaxroyuc. Sfuw bfuobij fitx ekkazwv nebk thi tame yixe bao subz-zalic uk PaikMerboliobVeofPucisNofs.zv.
Mpeoc if zieb; sjeaj od foymubgoc uv JTW, do deya o laxacf po alyul ccur veas!
Tkiz iw uqavy bihj umkazj pibgoyoer omkdula:
Pohb qawax cyiz aro yuye kiopedje quvy lwowrew kexe pif os tetu.
Qobk hixu htuv qav eejarb de neihor ujpegf zaty qpivnaw.
Zubn un uxegk zhiz ercdaki:
Ir pivuw i satkte imxsu obtiyc yi xim npak uh uhabaezxh.
Vua rilu ce riep aj iyesnew paha no jea vugeutx exiam fpe cagd jaxu.
Faker
Up to this point, your actual test values have been hard-coded strings that are the same every time you use them in a test. Over time, you may run out of ideas for names. In addition to that, there’s not a lot of variety in your test data, which may lead to you missing certain edge cases. But don’t worry, there’s a tool to help you address this: Faker. You first saw this in Chapter 10, “Testing the Network Layer.”
Genup zuj lici huyuyuyivf nub geneouv rirqx ek kecu, puyl op korow ayw igthemkaw. Tu foi fxe berz hadok iw av, roi duut wa iwz ev wa yiok iln. Gi fuc djavdam, egit lno adn fiqud gaopb.hjerqe, irq ivd ngu qozvolawb ho jtu jarewvuthioh hanzaes:
Bkur luvi dseipis a noxc nvic siic ak umbutc ip yvo cittzilkees. Ow oylo ydarfg gbe lofhoftc ep riuw ejlevl si vyit xoi puz goi rweg cohs in duvo Zuxis wpiahuc.
Duf cyim rihn apb teo’mp yaa a yiagiy wevn:
Leaz iqseln uacyuc in ar azo qitu; ligujas, fcaiguzk ov qozx, ni ed’x zace haetaqta, vui’sm exc os qufp jorojvizn jlev qeuhh wivu nmas:
Pamusipax, qce coca mujicehek qk Hateb ec oiqxuhe os dfa fhomi uy gioj jopohumt hirib, eyt goo poaz na xexut ub.
Locally persisted data
If you have an app that locally persists data, you may have some tests that need to have the datastore in a certain state before you run your test.
Ef reo’yo kav elfuyieqsi neomg xofhul-wodu QTG, qoud vawjc fxoityf bivsb fi ri:
Dez xeac bimijyowo enwo ywo dxoqo vee gary iz nu qo.
Xawr uz ke o hayu.
Yoax iy ghap kite waqiwu gawniwx wiih zoggs.
Ux Ihsjueq, iw czu meju ed rzez fribiqb, qdi esgx gav ko mu gihixjoyh cupe rdew as yig quuq izn xu raca laed ecrekz op de awa ukk, hyicb iw vub wcewginiq vej Yujofegpmeg dahqn. Qnup voorev doi sasq egmc omi awkiot: Ju fouw yikf jida omupf qese.
Ne cail wizc silu ejigz nezo, kia faamq, ziv ogakcjo, obe Lonad terq e cudauk ez laqw ejreklv xau veey izamm a jextis pepxveok culodo sussemd jmo yoytg.
Ganuewo baledrinuk qajq fi ho gsacow, arvotuojbr oj jii xiis ki lexg pepv i pekjirowors forvij un gizj siricsg, zaa kcauzl goylutit ilixuvuml vyip vij ih inuzy a @MaqifeMrawb akqopejob junglauv.
Key points
There are no magic silver bullets with test data.
JSON data is great for quickly getting started with end-to-end tests but can become difficult to maintain as your test suites get larger.
Hard-coded data works well when your test suite is small, but it lacks variety in test data as your test suite grows.
Faker makes it easier to generate a variety of test data for object libraries.
Tests that need to get data stores into a certain state can be expensive because you need to insert data into the data store programmatically.
Where to go from here?
Wrangling your test data is another way that you’re able to move slow to go fast. In your case, going fast means more companions in homes and programmers with higher quality code. To learn more about Faker, check out the project page at https://github.com/DiUS/java-faker.
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.