Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Coroutines Test 入門 / Android Test Night #8
Search
star_zero
March 10, 2023
Programming
2
1.1k
Coroutines Test 入門 / Android Test Night #8
star_zero
March 10, 2023
Tweet
Share
More Decks by star_zero
See All by star_zero
今からはじめるAndroidアプリ開発 2024 / DevFest 2024
star_zero
0
1.3k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
5.9k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
590
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
380
What's new in Jetpack / I/O Extended Japan 2022
star_zero
1
630
Kotlin 2021 Recap / DevFest 2021
star_zero
3
1.3k
Kotlin Symbol Processing (KSP) を使ったコード生成 / DroidKaigi 2021
star_zero
2
5.2k
What's new Android 12
star_zero
0
570
これからはじめるAndroid開発 / DevFest 2020
star_zero
4
700
Other Decks in Programming
See All in Programming
RubyKaigi Dev Meeting 2025
tenderlove
1
160
自分のために作ったアプリが、グローバルに使われるまで / Indie App Development Lunch LT
pixyzehn
1
160
State of Namespace
tagomoris
4
1.7k
AIコーディングの理想と現実
tomohisa
22
30k
The Efficiency Paradox and How to Save Yourself and the World
hollycummins
0
110
Bedrock×MCPで社内ブログ執筆文化を育てたい!
har1101
6
1k
Dissecting and Reconstructing Ruby Syntactic Structures
ydah
0
700
Chrome Extension Techniques from Hell
moznion
1
160
アプリを起動せずにアプリを開発して品質と生産性を上げる
ishkawa
0
2.8k
Java 24まとめ / Java 24 summary
kishida
3
500
Boost Your Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
1.7k
SwiftUI API Design Lessons
niw
1
290
Featured
See All Featured
How to Ace a Technical Interview
jacobian
276
23k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
32
5.4k
Reflections from 52 weeks, 52 projects
jeffersonlam
349
20k
Documentation Writing (for coders)
carmenintech
69
4.7k
Making Projects Easy
brettharned
116
6.1k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
The Cost Of JavaScript in 2023
addyosmani
49
7.7k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
227
22k
Rebuilding a faster, lazier Slack
samanthasiow
80
8.9k
Fireside Chat
paigeccino
37
3.4k
Transcript
Android Test Night #8 2023/03/10 Coroutines Test 入門
• Kenji Abe • @STAR_ZERO • Google Developers Expert for
Android, Kotlin • DeNA Co., Ltd.
// build.gradle dependencies { // ... testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4") }
supsend関数のテスト
class Sample { suspend fun run(): String { return "hoge"
} }
class SampleTest { @Test fun testRun() = runTest { val
sample = Sample() val result = sample.run() assert(result == "hoge") } }
class SampleTest { @Test fun testRun() = runTest { val
sample = Sample() val result = sample.run() assert(result == "hoge") } }
• runBlockingのようなもの • delay関数はすべてスキップされる ◦ Vertial Timeを制御することができる • TestScopeが使用される runTest
TestDispatchers
• StandardTestDispatcher ◦ runTestデフォルト ◦ TestCoroutineSchedulerを使用するシンプルなDispatcher • UnconfinedTestDispatcher ◦ Dispatchers.Unconfinedのようなもの
◦ トップレベルのlaunch/asyncがすぐに実行される TestDispatchers
class SampleTest { @Test fun testRun() = runTest { val
sample = Sample() val result = sample.run() assert(result == "hoge") } }
@Test fun test() = runTest { var result = 0
launch { result = 1 } assert(result == 1) }
@Test fun test() = runTest { var result = 0
launch { result = 1 } assert(result == 1) } ❌ Failed
@Test fun test() = runTest { var result = 0
launch { result = 1 } assert(result == 1) } ① ② ③
@Test fun test() = runTest { var result = 0
launch { result = 1 } runCurrent() assert(result == 1) } ✅ Success
@Test fun test() = runTest { var result = 0
launch { result = 1 } runCurrent() assert(result == 1) } ① ② ③ ④
@Test fun test() = runTest { var result = 0
launch { delay(1000) result = 1 } runCurrent() assert(result == 1) }
@Test fun test() = runTest { var result = 0
launch { delay(1000) result = 1 } runCurrent() assert(result == 1) } ❌ Failed
@Test fun test() = runTest { var result = 0
launch { delay(1000) result = 1 } runCurrent() assert(result == 1) } ① ② ③ ④ ⑤
@Test fun test() = runTest { // ... advanceUntilIdle() //
または advanceTimeBy(1001) assert(result == 1) } ✅ Success
@Test fun test() = runTest(UnconfinedTestDispatcher()) { var result = 0
launch { result = 1 } assert(result == 1) }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { var result = 0
launch { result = 1 } assert(result == 1) } ✅ Success
Mainスレッド対応
class Sample { suspend fun run(): String = withContext(Dispatchers.Main) {
"hoge" } }
@Test fun testRun() = runTest { val sample = Sample()
val result = sample.run() assert(result == "hoge") }
@Test fun testRun() = runTest { val sample = Sample()
val result = sample.run() assert(result == "hoge") }
@Before fun setUp() { Dispatchers.setMain(StandardTestDispatcher()) } @After fun tearDown() {
Dispatchers.resetMain() }
Flowのテスト
class Sample { val flow = MutableSharedFlow<Int>() suspend fun emit(value:
Int) { flow.emit(value) } }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { val sample = Sample()
val result = mutableListOf<Int>() val job = launch { sample.flow.toCollection(result) } assert(result.size == 0) sample.emit(1) assert(result.size == 1) assert(result.first() == 1) job.cancel() }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { val sample = Sample()
val result = mutableListOf<Int>() // ... }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { val sample = Sample()
val result = mutableListOf<Int>() val job = launch { sample.flow.toCollection(result) } // ... }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { val sample = Sample()
val result = mutableListOf<Int>() val job = launch { sample.flow.toCollection(result) } // ... }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { // ... val job
= launch { sample.flow.toCollection(result) } assert(result.size == 0) // ... }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { // ... val job
= launch { sample.flow.toCollection(result) } sample.emit(1) // ... }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { // ... sample.emit(1) assert(result.size
== 1) assert(result.first() == 1) job.cancel() }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { // ... val job
= launch { sample.flow.toCollection(result) } // ... job.cancel() }
@Test fun test() = runTest(UnconfinedTestDispatcher()) { // ... backgroundScope.launch {
sample.flow.toCollection(result) } // ... // job.cancel() }
Turbine (時間の都合上省略...) https://github.com/cashapp/turbine
まとめ
• runTest • StandardTestDispatcher / UnconfinedTestDispatcher • Dispatchers.setMain • backgroundScope
まとめ
ありがとうございました