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
DataStoreをテストする
Search
mkeeda
April 04, 2025
Programming
0
550
DataStoreをテストする
Shibuya.apk #52の発表資料です
https://shibuya-apk.connpass.com/event/349013/
mkeeda
April 04, 2025
Tweet
Share
More Decks by mkeeda
See All by mkeeda
アジャイル & スクラム入門
mkeeda
0
98
そのAPI、誰のため? Androidライブラリ設計における利用者目線の実践テクニック
mkeeda
2
5.4k
Android StudioのAIコーディングツール、 ぶっちゃけどうなん???
mkeeda
0
460
時計仕掛けのCompose
mkeeda
1
500
What's new in Firebase for building gen AI features気になったところ
mkeeda
0
890
手動DIの教訓
mkeeda
0
270
WebViewと向き合う
mkeeda
2
1.6k
お気に入りのAndroid Studio小技集
mkeeda
0
390
Scalable UI testing solutions かんたんまとめ
mkeeda
0
1.3k
Other Decks in Programming
See All in Programming
安いハードウェアでVulkan
fadis
1
810
AIコードレビューの導入・運用と AI駆動開発における「AI4QA」の取り組みについて
hagevvashi
0
560
Rethinking API Platform Filters
vinceamstoutz
0
910
GC言語のWasm化とComponent Modelサポートの実践と課題 - Scalaの場合
tanishiking
0
130
それはエンジニアリングの糧である:AI開発のためにAIのOSSを開発する現場より / It serves as fuel for engineering: insights from the field of developing open-source AI for AI development.
nrslib
1
580
20260315 AWSなんもわからん🥲
chiilog
2
180
Fundamentals of Software Engineering In the Age of AI
therealdanvega
2
290
車輪の再発明をしよう!PHP で実装して学ぶ、Web サーバーの仕組みと HTTP の正体
h1r0
2
400
ネイティブアプリとWebフロントエンドのAPI通信ラッパーにおける共通化の勘所
suguruooki
0
190
Everything Claude Code OSS詳細 — 5層構造の中身と導入方法
targe
0
150
Strategy for Finding a Problem for OSS: With Real Examples
kibitan
0
110
飯MCP
yusukebe
0
370
Featured
See All Featured
How to Ace a Technical Interview
jacobian
281
24k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
130
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
110
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
390
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.3k
The Cost Of JavaScript in 2023
addyosmani
55
9.8k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
150
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.4k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.2k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
1
1.5k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.5k
Transcript
DataStoreをテストする Shibuya.apk # 5 2 向井 田 一 平 (@mr_mkeeda)
• 向井 田 一 平 (むかいだ いっぺい) • 𝕏 :
@mr_mkeeda • Github: @mkeeda • Android Engineer at Cybozu, Inc • 最近ハマっているもの: ガンニバル🍖 2
DataStore “を” テストする • androidx.DataStore • DataStoreの処理 自 体をテストする •
ex. 独 自 実装のSerializerを使ったデータの読み書きをテスト • DataStoreを含めたテスト対象をテストする • ex. DataStoreをモックせずにRepositoryの実装をテスト 3
DataStoreテストの流れ 1 . DataStoreインスタンスを作成 • CoroutineDispatcherの差し替え ⭐ 2 . 前提の状況を作る
• 事前にデータを書き込んでおく • 別のテストケースで書き込んだデータの削除 ⭐ 3 . テストしたい処理を実 行 4 . 期待する振る舞いを検証 • データ書き込みしたファイルの中 身 を検証 ⭐ 4
CoroutineDispatcherの変え 方 5 val Context.testDataStore by dataStore( fileName = "test_file",
serializer = StringSerializer(defaultValue = "default"), scope = CoroutineScope(UnconfinedTestDispatcher() + Job()) // ⭐ ) // or val testDataStore = DataStoreFactory.create( serializer = StringSerializer(defaultValue = "default"), scope = CoroutineScope(UnconfinedTestDispatcher() + Job()), // ⭐ produceFile = { context.dataStoreFile(fileName = "test_file") } )
データの後始末 6 internal fun Context.clearDataStore() { File(filesDir, "/datastore").deleteRecursively() } @Before
fun setUp() { context.clearDataStore() } // or val testDataStore = DataStoreFactory.create( serializer = StringSerializer(defaultValue = "default"), produceFile = { /** Ұ࣌ϑΝΠϧΛ࡞Δ **/ } )
書き込まれたファイルの検証 方 法 7 val testDataStore = DataStoreFactory.create( serializer =
StringSerializer("default"), produceFile = { context.dataStoreFile(fileName = "test_file") } ) testDataStore.updateData { "Hello world" } // ⭐ val storedFile = context.filesDir.findFileBy("test_file") storedFile ?. readText() .shouldBe("Hello world") .shouldNotBe("default")
8 internal fun File.findFileBy(fileName: String): File? = searchFileRecursively(directory = this,
fileName) private fun searchFileRecursively( directory: File, fileName: String, ): File? { directory.listFiles() ?. forEach { file -> if (file.isDirectory) { searchFileRecursively(file, fileName) ?. let { return it } } else if (file.name.contains(fileName)) { return file } } return null }
ファイル参照の競合 • DataStoreインスタンスは シングルトンで使う設計 • 同 一 のファイル名を 同時に参照するとエラー •
AndroidTestだと1プロセス内で 同 一 参照があるとエラー • 複数のテストを実 行 しないと エラーに気付けない! 9 DataStore ファイル class TestA class TestB fun test 1 () fun test 2 () fun test 3 () ⚠ ⚠ ⚠
ファイル参照の競合を回避する • ファイル名をテストケース単位で ユニークにする • JUnitのRuleを作るといいかも (試してない) 1 0 DataStore
TestA_test 1 _ fi le class TestA class TestB fun test 1 () fun test 2 () fun test 3 () DataStore TestA_test 2 _ fi le DataStore TestB_test 3 _ fi le
ファイルの参照を解放させたい • DataStoreは稼働中、書き込み先のファイルを占有する • 2番 目 に参照してきたDataStoreはエラーになる • では、こういうのはどうやってテストする? 1
. DataStoreAでデータを書き込み 2 . アプリ再起動などでDataStoreAが破棄 3 . 1で書き込んだデータをDataStoreBで読み込める 1 1
1 2 val testDataStore1 = DataStoreFactory.create( produceFile = { context.dataStoreFile(fileName
= "test_file") } ) testDataStore1.updateData { "Hello world" } // ΞϓϦϓϩηεΛऴྃͤ͞Δ // ʁʁʁ⭐ val testDataStore2 = DataStoreFactory.create( produceFile = { context.dataStoreFile(fileName = "test_file") } ) // ॻ͖ࠐΜͩσʔλ͕ಡΈࠐΊΔ͜ͱΛ֬ೝ testDataStore2.data.first() shouldBe "Hello world"
Jobを完了させるとDataStoreはファイル参照を解放する 1 3 val dataStoreJob = Job() val testDataStore1 =
DataStoreFactory.create( scope = CoroutineScope( UnconfinedTestDispatcher() + dataStoreJob // ⭐ ), produceFile = { context.dataStoreFile(fileName = "test_file") } ) dataStoreJob.complete()
DataStoreテストまとめ • 基本編 • CoroutineDispatcherはscopeを差し替える • テスト後の後始末はファイルごと消す • DataStoreの書き込み挙動はファイルの中 身
を検証する • 上級編 • ファイル参照の競合に気をつける • DataStoreのファイル参照を解放するには scopeに含めたJobを完了させる 1 4
参考 • DataStore and testing | Android Developers | Medium
https://medium.com/androiddevelopers/datastore-and-testing- edf 7 ae 8 df 3 d 8 • androidx.DataStoreのテストコード https://cs.android.com/androidx/platform/frameworks/support/+/ androidx-main:datastore/ 1 5