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.2k
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.4k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
6.3k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
610
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
400
What's new in Jetpack / I/O Extended Japan 2022
star_zero
1
650
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
580
これからはじめるAndroid開発 / DevFest 2020
star_zero
4
720
Other Decks in Programming
See All in Programming
Honoアップデート 2025年夏
yusukebe
1
850
Portapad紹介プレゼンテーション
gotoumakakeru
1
130
なぜ今、Terraformの本を書いたのか? - 著者陣に聞く!『Terraformではじめる実践IaC』登壇資料
fufuhu
4
650
Constant integer division faster than compiler-generated code
herumi
2
690
Rancher と Terraform
fufuhu
0
100
あなたとJIT, 今すぐアセンブ ル
sisshiki1969
1
720
Flutterと Vibe Coding で個人開発!
hyshu
1
260
コンテキストエンジニアリング Cursor編
kinopeee
1
700
UbieのAIパートナーを支えるコンテキストエンジニアリング実践
syucream
2
700
State of CSS 2025
benjaminkott
1
120
自作OSでDOOMを動かしてみた
zakki0925224
1
1.4k
MCPで実現するAIエージェント駆動のNext.jsアプリデバッグ手法
nyatinte
6
850
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
56
5.8k
Music & Morning Musume
bryan
46
6.7k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Designing for humans not robots
tammielis
253
25k
Site-Speed That Sticks
csswizardry
10
780
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
30
9.6k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
890
Building Flexible Design Systems
yeseniaperezcruz
328
39k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
Making the Leap to Tech Lead
cromwellryan
134
9.5k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
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
まとめ
ありがとうございました