Slide 1

Slide 1 text

Deep Dive Into Coroutine Testing @mambo_bryan 01

Slide 2

Slide 2 text

02 Design Centric Engineer Brian Odhiambo Dishwasher @ Baobab Circle Co-organizer @ KotlinKenya Maintaining @ KotlinBits Crazy about that UI/UX & Kotlin

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

Testing The theory of testing

Slide 6

Slide 6 text

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?

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

runBlocking { ... } runBlockingTest { ... } Evolution Of kotlinx.coroutines.test runTest { ... }

Slide 10

Slide 10 text

Suspending Testing suspended functions

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

New Coroutines Those fire & forget coroutines

Slide 16

Slide 16 text

runBlocking { ... } runBlockingTest { ... } runTest { ... } TestCoroutineScheduler TestDispatcher Evolution Of kotlinx.coroutines.test runTest { ... } TestScope

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

starts job immediately use selectively UnconfinedTestDispatcher default dispatcher queues work StandardTestDispatcher TestDispatchers

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

One Last Thing For the community

Slide 25

Slide 25 text

KotlinBits 😎 A fun and easy way to learn Kotlin in small bits and pieces. React, Comment & Share https://kotlinbits.vercel.app

Slide 26

Slide 26 text

Thank you So much DroidPwani. You guys have been awesome & fantastic

Slide 27

Slide 27 text

16 mambo_bryan MamboBryan Have a nice Kotlin KotlinBits kotlinbits.vercel.app