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.3k
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.5k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
6.8k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
640
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
460
What's new in Jetpack / I/O Extended Japan 2022
star_zero
1
690
Kotlin 2021 Recap / DevFest 2021
star_zero
3
1.3k
Kotlin Symbol Processing (KSP) を使ったコード生成 / DroidKaigi 2021
star_zero
2
5.3k
What's new Android 12
star_zero
0
600
これからはじめるAndroid開発 / DevFest 2020
star_zero
4
750
Other Decks in Programming
See All in Programming
AI主導でFastAPIのWebサービスを作るときに 人間が構造化すべき境界線
okajun35
0
420
Oxlint JS plugins
kazupon
1
1.1k
日本だけで解禁されているアプリ起動の方法
ryunakayama
0
360
ぼくの開発環境2026
yuzneri
1
290
ふん…おもしれぇ Parser。RubyKaigi 行ってやるぜ
aki_pin0
0
120
The Ralph Wiggum Loop: First Principles of Autonomous Development
sembayui
0
3.7k
Go 1.26でのsliceのメモリアロケーション最適化 / Go 1.26 リリースパーティ #go126party
mazrean
1
310
PostgreSQL を使った快適な go test 環境を求めて
otakakot
0
370
LangChain4jとは一味違うLangChain4j-CDI
kazumura
1
120
今、アーキテクトとして 品質保証にどう関わるか
nealle
0
200
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
1
500
JPUG勉強会 OSSデータベースの内部構造を理解しよう
oga5
2
220
Featured
See All Featured
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
180
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
220
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
280
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
330
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
62
50k
A Tale of Four Properties
chriscoyier
162
24k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
14k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
2
65
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.6k
Building Adaptive Systems
keathley
44
2.9k
Art, The Web, and Tiny UX
lynnandtonic
304
21k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
380
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
まとめ
ありがとうございました