Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Coroutines IV : Deep Dive Into Coroutine Testing

Coroutines IV : Deep Dive Into Coroutine Testing

These are the slides for the last session on coroutines. In this session I how we can test suspending functions and functions that launch coroutines using coroutine builders.

Brian Odhiambo

July 03, 2023
Tweet

More Decks by Brian Odhiambo

Other Decks in Technology

Transcript

  1. 02 Design Centric Engineer Brian Odhiambo Dishwasher @ Baobab Circle

    Co-organizer @ KotlinKenya Maintaining @ KotlinBits Crazy about that UI/UX & Kotlin
  2. Ensuring It Works 03 testing! assertions! failures! Suspending Functions Testing

    functions that immediately return a value Non Suspending Functions Testing functions that launch other coroutines
  3. What are coroutines? What are coroutine builders? A Small Recap

    Why use coroutines? What is a coroutine context, why do we need it? What are jobs, and their state? What are dispatchers and how do they help? And So much more... Just like DSTV
  4. improve code quality detect vulnerabilities detect edge cases early being

    kind to the next developer so on & so forth Evaluating and verifying the accuracy of your code What is testing? Why should we test?
  5. improve code quality detect vulnerabilities detect edge cases early being

    kind to the next developer so on & so forth Evaluating and verifying the accuracy of your code What is testing? Why should we test? action performed WHEN expected outcome of the action SHOULD Thing under test GIVEN
  6. Example fun add(a : Int, b : Int) = a.plus(b)

    fun main() { // given & when val actual = add(1, 2) val expected = 3 // should if(expected != actual) println("Test Failed !") else println("Test Passed...") } 06
  7. runBlocking { ... } runBlockingTest { ... } Evolution Of

    kotlinx.coroutines.test runTest { ... }
  8. suspend fun fetchAuthors() { delay(1_500L) return listOf("a", "b", "c") }

    @Test fun fetchAuthorsTest(){ val list = fetchAuthors() assertContains(list, "a") } 06
  9. suspend fun fetchAuthors() { delay(1_500L) return listOf("a", "b", "c") }

    @Test fun fetchAuthorsTest(){ val list = fetchAuthors() assertContains(list,"a") } 06
  10. import kotlinx.coroutines.text.runTest suspend fun fetchAuthors() { delay(1_500L) return listOf("a", "b",

    "c") } @Test fun fetchAuthorsTest() = runTest { val list = fetchAuthors() assertContains(list,"a") } 06
  11. import kotlinx.coroutines.text.runTest suspend fun fetchAuthors() = withContext(Dispatchers.IO) { delay(1_500L) return

    listOf("a", "b", "c") } @Test fun fetchAuthorsTest() = runTest { val list = fetchAuthors() assertContains(list,"a") } 06
  12. runBlocking { ... } runBlockingTest { ... } runTest {

    ... } TestCoroutineScheduler TestDispatcher Evolution Of kotlinx.coroutines.test runTest { ... } TestScope
  13. import kotlinx.coroutines.text.runTest suspend fun fetchAuthors(dispatcher: CoroutineContext) = withContext(dispatcher) { delay(1_500L)

    return listOf("a", "b", "c") } @Test fun fetchAuthorsTest() = runTest { val list = fetchAuthors(testDispatcher) assertContains(list,"a") } 06
  14. import kotlinx.coroutines.text.runTest ... fun addAuthors() { launch { database.add("a") }

    launch { database.add("b") } } fun fetchAuthors(){ return authors } ... @Test fun fetchAuthorsTest() = runTest { val repo = AuthorRepository() repo.addAuthors() val list = fetchAuthors() assertContains(list,"a") } 06
  15. import kotlinx.coroutines.text.runTest ... fun addAuthors() { launch { database.add("a") }

    launch { database.add("b") } } fun fetchAuthors(){ return authors } ... @Test fun fetchAuthorsTest() = runTest { val repo = AuthorRepository() repo.addAuthors() val list = fetchAuthors() assertContains(list,"a") } 06
  16. import kotlinx.coroutines.text.runTest ... fun addAuthors() { launch { database.add("a") }

    launch { database.add("b") } } fun fetchAuthors(){ return authors } ... @Test fun fetchAuthorsTest() = runTest { val repo = AuthorRepository() repo.addAuthors() advanceUntilIdle() val list = fetchAuthors() assertContains(list,"a") } 06
  17. import kotlinx.coroutines.text.runTest ... fun addAuthors() { launch { database.add("a") }

    launch { database.add("b") } } fun fetchAuthors(){ return authors } ... @Test fun fetchAuthorsTest() = runTest(UnconfinedTestDispatcher()) { val repo = AuthorRepository() repo.addAuthors() // advanceUntilIdle() val list = fetchAuthors() assertContains(list,"a") } 06
  18. import kotlinx.coroutines.text.runTest class AuthRepository(scope: CoroutineContext){ fun addAuthors() { scope.launch {

    database.add("a") } scope.launch { database.add("b") } } fun fetchAuthors(){ return authors } ... @Test fun fetchAuthorsTest() = runTest() { val repo = AuthorRepository(testDispatcher) repo.addAuthors() val list = fetchAuthors() assertContains(list,"a") } 06
  19. KotlinBits 😎 A fun and easy way to learn Kotlin

    in small bits and pieces. React, Comment & Share https://kotlinbits.vercel.app