Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Coroutines Test 入門 / Android Test Night #8
Search
star_zero
March 10, 2023
Programming
1.4k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Coroutines Test 入門 / Android Test Night #8
star_zero
March 10, 2023
More Decks by star_zero
See All by star_zero
今からはじめるAndroidアプリ開発 2024 / DevFest 2024
star_zero
0
1.7k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
7.3k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
710
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
520
What's new in Jetpack / I/O Extended Japan 2022
star_zero
1
740
Kotlin 2021 Recap / DevFest 2021
star_zero
3
1.4k
Kotlin Symbol Processing (KSP) を使ったコード生成 / DroidKaigi 2021
star_zero
2
5.3k
What's new Android 12
star_zero
0
640
これからはじめるAndroid開発 / DevFest 2020
star_zero
4
790
Other Decks in Programming
See All in Programming
[DroidKnights 2026] Workflow AX: From Auto-Documented Policies to E2E Testing
raeminkang
0
540
AWS CDKを理解するために公式の定義を深掘って解説してみる / Understanding AWS CDK by Digging into Its Official Definition
akihisaikeda
3
280
AI時代のFlutter品質設計 — アプリ品質を守るQuality Layers
omatty198
0
360
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
300
AI駆動開発4年目の現在地(『あなたはFDEになるべきか?』イベント資料)
kumaiu
0
280
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
150
そのデザイントークン、Flutterでも同じ見た目になりますか?
nakamizu
0
310
조합이폭발하는디자인시스템이걸눈으로도테스트하라고요
giljongyu
0
730
作れるエンジニアから、価値を届けるエンジニアへ
ryunakayama
1
240
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
200
あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期
hasutosasaki
1
2.2k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
600
Featured
See All Featured
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
420
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
エンジニアに許された特別な時間の終わり
watany
109
250k
Docker and Python
trallard
47
4.3k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
660
Color Theory Basics | Prateek | Gurzu
gurzu
1
510
How to Think Like a Performance Engineer
csswizardry
28
2.9k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.7k
Embracing the Ebb and Flow
colly
88
5.2k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
620
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
まとめ
ありがとうございました