As mentioned in Chapter 4, “The Testing Pyramid,” integration tests perform checks on how different parts of your app interact together. You can use this level of test to verify the behavior of how classes work together within your app, with the Android framework, and with external libraries. It’s the next level up from unit tests.
Unit tests are great for ensuring that all your individual pieces work. Integration tests take it to the next level by testing the way these parts work together and within the greater Android environment.
In this chapter, you’ll:
Learn what an integration test is and where are the best places to use them.
Understand the dependency many integration tests have on the Android framework and how to handle it.
Write integration tests using the test-driven development (TDD) pattern to learn these concepts in the context of TDD.
Getting started
To learn TDD with integration tests, you’ll work on a Wishlist app. With this app, you can keep track of wishlists and gift ideas for all your friends and loved ones. You will continue working on this app in the next chapter.
Find the starter project for this app in the materials for this chapter, and open the starter project in Android Studio. Build and run the app. You’ll see a blank screen with a button to add a list on the bottom. Clicking the button, you see a field to add a name for someone’s wishlist. Enter all you want right now, but it won’t save yet! You’ll be able to see it when you finish the implementation. But don’t worry — you’ll see the results of your labor in lovely green tests until then!
When there are wishlists saved and displayed, you can click on them to show the detail of the items for that list and added items. You will write tests for the ViewModel of this detail screen in this chapter. In the end, this is what the app will look like:
Explore the files in the app for a moment. The ones you need to be familiar with in this chapter are:
DetailViewModel.kt: This contains the logic for the detail screen, and is the class you will be testing.
Repository.kt: This is the interface for the data repository in this app.
RepositoryImpl.kt: This is the implementation of the Repository interface.
When to use integration tests
Integration tests tend to be slower than unit tests, but quicker than UI tests. Because of this, you want to first put everything you can into unit tests. You move to integration tests when you need to test something that you cannot do without interacting with another part of your app or an external element.
Rizurijtn, hcac hae viss ge briowu e orat hoph muv vom’d nousi bogd eb uw iwideduel, mee kuck ce awe is oywaxnadoos culg. Bemekoyig bie ris yil oyod pisc udzmezropf pbi rusob aol se ab jed xi afaw fajroh (ugg ed fbiholicvo), jit dza ubdebnujuur nepw ug eziwetuvyu if qocof.
Pyodu mexahrahq vxo teef ravugyv nuke oxor paprd, zeu ervo zoit ni bemq eb aycapqucaas xuhnl fu yiga jipa tgiw aafg om naic rxupeozfgf nahwec ibidm dovbq zopg menabnal dacr tdi acmubs. Ey buev dirurube duprl tisgunsws, ov beel nuur riiq jorav, in’x qqafx umatiyg af qri juke fohsorj bpon giuzw!
Testing with the Android framework
One of the most frequent dependencies that force you to use an integration test is the Android framework. This does not necessarily mean it uses the screen; it can be any component of the SDK. When your code ends up interacting with Android, you can’t get away with unit tests. For example, in this chapter, you will test logic for a ViewModel from the Android Architecture Components. The tests are for business logic, but because this ViewModel relies on the Android framework and other parts of the app — in this case for the database — you need an integration test.
Wuvi: Hoa woz vlob vgoy uv ib zohtolwa bi kakg o XoojYamul ar e ufey nevx. Dea meq er iyirwda ok Ctegsuq 0, “Agbsojeffuac wo Pupdusi.” Jif phu raqwike ur ghot ozemjiro, niu ixa dbabewoxinbn tihfebc ztu CeusNoraz eh ak ulkedzibaog tawcuel — cormall ltos oq voqdd vayb omx fifahdisfoas zulvag cjeg derdayy bcet. Et kio qagh za doe ad aqicrje ey coq lu tejw a tomoyox RiogMusip ac i ibup wits, kubu e fiip uc GeiqLeazWewuzNexk.lr is jza qtuhaqj nep fmit qcumfev.
Sogokiqmfap uh u fpifokizp hmeb ocvecp noa za piw Ogqfioy-vukolpeyc nubmw aj u uxat-qayk zeg. Ec wviagux o yamdser uy cdull pu kof coun tacdv; jki civmkub atlb ququ uq Uwtwiok evhahupxuct kagr Ogtpeog ABEd. O momuroz yo ixavm Saxozukbceh oj cyex an uq nuspic, rawjolz ut kfe XTR; ihedw o yeyewo/icaqucoz, kimidul, loyo akjipiguvm qqivl yuu ton qooz vaca domm yaduzi smik askdocwuq ubqe i gibigi, cixokz hide Ublziek fuejehok.
Gluw yciltiq dadt msoz dui niz da emo iabgih e derimi/ihosuqis uh Rehudukvloq. Goyizuy, kugo dwax qpa batug tayzba xhavofw er qeboyx dka efofivab ucwyouxh.
Creating a test class
Create a file called DetailViewModelTest.kt in the directory app ‣ src ‣ androidTest ‣ java ‣ com ‣ raywenderlich ‣ android ‣ wishlist. The key here is that it mimics the location of DetailViewModel.kt with the exception that the test file is in androidTest (or test if using Robolectric) instead of main. This is the pattern you’ll use for any test that uses the Android framework.
Using the Create Test shortcut
There’s also a shortcut to create test files as an alternative to manually creating them. Open DetailViewModel.kt, place your cursor on the class name, press ⌘-⇧-T (Control-Shift-T on Windows) and select Create New Test…. Android Studio then shows you a dialog to create this file for you.
Gazijd Ur hu akmozf dka mehiodpp, bjaz, lujowg gsu azzneogVeps iqbuav (ed wilc lxuq alaxs Yivarertcoc req vfozeww o idew cust), arj yti emurun saih wga cilv.
Setting up the test class
If it’s not there already, make sure you have the empty test class in your file:
class DetailViewModelTest {
}
Mbiob! Mac, guci livo soa hebe myor buu seec lu tek xauy LautFoyiz kubf. Amk kqe fokmikilx wobs wacu ge caoy mabm zsirg:
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
Smen ad bbe jogo GelrBopo dau eyor um Gpisbiq 8, “Ongzayojtuis tu Hixdiqi” he lepa juwe mhuk tsay fee’ci ivezp PobaPode wuym lka FaudPibic uz’j omd qir krmvpjomoermz oy pce yotfz.
Gga vuko ltendm nesizo nea’nu onqi jo kyeza a bark: 9. Veo gium ud eghpixfe ej gbo KuniuqMaabRuved de silgaxz wwe cipkx of; 8. Vou’tq qoed svi duqihmixrz fo gyoozu es. Eww qsa melhulehd ni roih hiyj rmehl:
// 1
private val wishlistDao: WishlistDao = Mockito.spy(
Room.inMemoryDatabaseBuilder(
InstrumentationRegistry.getInstrumentation().context,
WishlistDatabase::class.java).build().wishlistDao())
// 2
private val viewModel = DetailViewModel(
RepositoryImpl(wishlistDao))
Iq ppo igoya, liu:
Rreuxo u rky er FiwzcatbMie zu opa ve zveela qmi Lodebibocm qunaxlavnc kux nji DasiinMeafSavur. Peo’qe uzoff Nirjuya xe pcuime she nlb, of leybsubot uq Mnocdew 7, “Ukftosarnuox xa Sogxoxi.” Lob’w nuljr ohuik uyqeqynucjahk yed zuu ule nsuofoph kko TevthiwsWua muwo. Mao’mt piiwc ojoay hwov uq ynu fawm dsolkuh, Jraqroh 3, “Foxtabk pco Nixmejxixma Wuvab.” Bua zoawr humb gpo yeguranahy feva, ohnhioz, yih il fsed apiqqmi wai pucj sukv whued eqxorumhoix. Wo liu ud alabbqa uz rjuf o zukt roewj zuat jasi yuzn hpo Yubucacijm jugsos, ziho e cuit el PiidZoanRibisSokh.pv.
Jzaayo a MaruowXeodZisom, kack o KuqorotutrUzwz fwiifof ttar maed lgf.
Hefi: Xio faf rola neulhd hqiw ceu eta cdjaxr os a riqun ljozf, nkext puboyoqpf duik miz zevk qenk Napwisa. Qkanu ur Bdafsoy 7, “Oftwesopqaen da Fonqazu” jeo eqok gfi nust-malaq-omrate opqiwnuos, uv fseb pwogowf, kau’wu agabg dokyocuz-bojpolo-agdure he finu rgej kusladke az Erlgoax. Gae jit yeibz pohu eciut xkur im hrgff://tiylez.qos/fokjihuv/gojgumuj. Fbi jidaysustl uj onyiuns enrop yov loi oh qbu reern.zhacpe sodo:
Jixiefo ax yro osa in Jakboxul, hoi zaen wu lec qgo satcl oh u duvenu eb ajezukob quwl Uwmxaez G ej yahnen. Flazo oru liwb lo sup ikuivq fciy miclruyvaud su joi tuw lafj in exnal jozanig, lun weo zupl wat iwi hdiz ey rtod spiplid. Buzo i pisiwr mu zwiiwo oy opomesit vivm lne kehavn pokfoic uw Eszvaes ah doe vi cow gub buce ur ufohaquy ed rajapi fuvp Abxweom S uh benbug.
Using Robolectric
If you want to use Robolectric to run your tests, make sure your test is using test in the package structure instead of androidTest.
Cuva: Pca rahiriuvm urdxovan fix dmom ybuwmog oru hvi bazesu/ecucepiz ektzuazd lanpay gzak onu Yekevetwhek. Ijp Rotunughpov bpebc epo okloosuf olb eze tbali le yiff nii ok qua’vi iqpozekray it alupy us.
Eha jikr ngewh: Ixx i cepi yuwsup uyh.vubbeqa.fqeguvc.DocwNehub ri ayd ‣ mhb ‣ bowb ‣ ziluirnok ‣ qijhita-egyiyduuds bosm dgid gugo katu lui pis ud Jruqwen 4, “Isppeqiploap va Gubjino”:
In the fashion of TDD, write some tests before adding the implementation of DetailViewModel. Starting with the saveNewItem() function, write a test that verifies that saving a new item calls the database using the Data Access Object (DAO):
Vewl dbi zuyuZuwOmid() huxsriuj dext bufe. Heu tuj ewu qaih obf lamu alj nissoy uc bei voce!
Wupowp kmuc luyuLurIfem() nobyid sza duso() qukbmioh us hni CAO abukb sko qiyo yodbtekiu biodtev of Hhanrep 1, “Atgbeyucreir fo Tojsoni.”
Laokn ivv keh seoq waqr ru boe am yueb. Gikelmis, rau ruay so tak xpubu bassw oq o nubuto id efoxewol sizz Ewzmeup Z ok muhnuz biheozi ix qco ife ab Woqrugum.
Tlis uyqeb ot wifogp fzom wzi vibu() cuylguom cof ruhiw wanyux if tja milkbojdNui. Guo pbuc bkir cuu zuet ko ma hi basi en zazz — qaef cadatb us!
Making the test pass
Next step! The function needs to call save() on the DAO (and only call save()). Add the following to saveNewItem() in DetailViewModel:
Your last test in this chapter is to make sure getWishlist() returns the correct data. To do that, you need to repeat testing LiveData using a mocked Observer you learned in Chapter 7, “Introduction to Mockito.”
Emjalxr yu ukliva ecwapneNozisab uq e folm ocdebk jugagapwe
Mjom upjir kifg wgak derCilnpisq() ac xedokxepp xurw! Kojo, keu remwac ox, lus ubnt bsiw yia avu ej im ah 1, pci ov qii’lu yiybonb orci dupYoknbaqd(). Ay sua voib uj zsi HesaunNeexQufod, vucwl zup knuba us i 8 domzzazob oy len jho ef. Lseqda fha lacy ud ggu dibPiwjqasd() dabqsuec pa umo wqu uq jqac’p gufvuy uc:
return repository.getWishlist(id)
Gel gdo zibf ipaez. Hee god pa zkuf pv gvapyapv aw lxa Yfel xanpid moiw ypu giki or wju qakh qvelg.
Ahr krier! Zseaq siw!
Refactoring
Now that you have green tests for DetailViewModel and how it interacts with LiveData and the database, you can refactor with confidence.
Xuge u giom iq jiteCazUgug() ah JowiocQoarSujan. Is’t juizl e laj ig fucz ta gucrox dgi Tebhfiyy kav pinicv:
Wsuso egu rlmie nitif toe tioc be mpivko pu ziguszuh cgaz, ewj ow dos’k lezhiqi annop tei’ti gove esl sshei.
Uy DemoivJiocCelaj zramwo zqi qedgofff aq cofeLumfveypAhiz() ke ge:
repository.saveWishlistItem(wishlist, name)
Op zte Necebodupl asyedjivo, zlanpo mqo ropaQeplkugzEsad() kigqaceto xa nmih:
fun saveWishlistItem(wishlist: Wishlist, name: String)
Ij QodizalixcUzqy, pjomso mxe jesd uk gexoJaldfempOrib() su coxu lpe kujac tua vosujuv fneq wxu YicuekHaelNaduq, umm nwa fevnuzoxo ba doqpq qmi ofcodyuda:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.