Proto DataStore のマスター テスト:実践ガイド
前回の記事では、アプリケーションで Proto DataStore を使用する方法について説明しました。この記事は、アプリケーションの 1 つで Proto DataStore を使用した経験の一環として書きました。
その後、得た知識を使用してそのアプリケーションで Proto DataStore のテストを作成するとどうなるかを確認したいと思いました。
オンラインでガイダンスを検索してもあまり解決できなかったので、それを探している人のために私の知識を共有しようと思いました。最悪の場合、それは私の子孫に関わることになるでしょう。
検索でこの記事を見つけましたが、この記事は主に Preferences DataStore のテストに焦点を当てており、Proto DataStore ではありません。次のように述べられています。
「ただし、このマテリアルはProto DataStore のセットアップに使用できることに注意してください。 プリファレンスに非常に似ているため、テストします。」
しかし、その後を追ってみると、依存関係以外には類似点があまりなく、独自の Proto DataStore をテストするには別のロジックを導入する必要があることがわかりました。
セットアップ
アプリケーションの build.gradle ファイルに、次の依存関係を追加します。
dependencies {
///.....
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
}
$compose_version は、プロジェクト レベルの build.gradle ファイルで定義した変数です。
次に、androidTest に移動します。 ディレクトリを作成し、新しいファイルを作成します。通常、Proto DataStore と対話するリポジトリ クラスがあるため、このファイルに YourRepositoryClassNameTest という名前を付けることができます。 MyRepositoryTest という名前を使用します。 .
Proto DataStore 自体のテストを詳しく調べる前に、Proto DataStore をインスタンス化する必要があります。これに関するドキュメントをオンラインで見つけようとすると、情報はほとんどありません。
Proto DataStore のインスタンス化は、次のようにグローバル コンテキストで使用されます (テスト シナリオで使用されない場合)。
private val Context.myDataStore: DataStore<MyItem> by dataStore(
fileName = DATA_STORE_FILE_NAME,
serializer = MyItemSerializer
)
そうですね、テスト クラス内でこれを行うことはできません。なぜなら、上記のコードをコピーして貼り付けることはできますがそれができないからです。 アクセス DataStore オブジェクト。次のようにアプリケーション コンテキストを取得できます。
ApplicationProvider.getApplicationContext()
しかし私たちの myDataStore オブジェクトはそれを通じて利用できなくなります。
では、何ができるでしょうか?
上にリンクされた記事には、PreferenceDataStoreFactory.create メソッドを使用して Preference DataStore を作成する方法の例が記載されています。
fun create(
corruptionHandler: ReplaceFileCorruptionHandler<Preferences>? = null,
migrations: List<DataMigration<Preferences>> = listOf(),
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
produceFile: () -> File): DataStore<Preferences>
ただし、Preference DataStore を使用していないため、これは機能しません。うまくいくのは、次のように DataStoreFactory.create メソッドを使用することです。
fun <T : Any?> create(
serializer: Serializer<T>,
corruptionHandler: ReplaceFileCorruptionHandler<T>? = null,
migrations: List<DataMigration<T>> = listOf(),
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()), produceFile: () -> File): DataStore<T>
このメソッドにはいくつかの引数があります (デフォルト値を持つものもあります) が、それらすべてを渡す必要はありません。
- シリアライザー クラス
- Proto DataStore のファイルを作成するためのラムダ メソッド
dataStore = DataStoreFactory.create(
produceFile = {
testContext.dataStoreFile(TEST_DATA_STORE_FILE_NAME) },
serializer = MyItemSerializer
)
testContext を取得します。 投稿者:
private val testContext: Context = ApplicationProvider.getApplicationContext()
Proto DataStore が正常に作成されたら、それに対するいくつかのテストの作成に進むことができます。 Proto DataStore のインスタンスを依存関係として受け取るリポジトリ クラスがあることに注意してください。そのため、Proto DataStore を作成した後、リポジトリ クラスのインスタンスを作成する必要があります。
private val repository = MyRepository(datastore)
まず、Proto DataStore の初期状態を確認するテストを作成しましょう。 Proto DataStore 自体は、使用できるフローを公開します。
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun repository_testFetchInitialState() {
runTest {
testScope.launch {
val dataStoreObject = repository.myFlow.first()
// Insert here whatever we want to assert from our
// Proto DataStore. I.E. a flag whose initial value is false
assert(dataStoreObject.myFlag == false)
}
}
}
☝️ すでにお気づきかもしれませんが、オプトイン アノテーションを使用しています。 ここです。これは、(現在) 私たちが使用している API は実験的なものであり、使用するときにそのようにマークする必要があるためです。
DataStore のフローにアクセスしているため、 、testScope でラップする必要があります。 。 TestScope は次の操作で作成されます。
@OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = TestCoroutineDispatcher()
@OptIn(ExperimentalCoroutinesApi::class)
private val testScope = TestCoroutineScope(dispatcher)
実行して、最初の Proto DataStore テストをお楽しみください。
2 秒くらい楽しかったです。
もっと意味のあることをしましょう。
Proto DataStore の中にオブジェクトのリストがあり、そこにアイテムを追加するときにその状態をテストしたいと想像してください。
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun repository_testAdditionOfItem() {
runTest {
testScope.launch {
//1
val item: MyItem = MyItem.newBuilder().setItemId(UUID.randomUUID().toString())
.setItemDescription(TEST_ITEM_DESCRIPTION).build()
//2
repository.updateItem(item)
//3
val items = repository.myFlow.first().itemsList
assert(items.size == 1)
//4
assert(items[0].itemDescription.equals(TEST_ITEM_DESCRIPTION))
}
}
}
<オル> データストアにリークがあります
上記のテストを一度に実行しようとすると、すぐに実行時にエラーが発生します。
同じファイル /data/user/0/com.example.app/files/datastore/dataStore_filename.pb に対して複数のデータストアがアクティブになっています。データストアをシングルトンとして維持するか、同じファイル上でアクティブなデータストアが 2 つないことを確認する必要があります (スコープがキャンセルされていることを確認することによって)。
まあ、それは問題だ。テスト クラスでは DataStore インスタンスを 1 つだけ作成しました。
ここで何が起こっているのでしょうか?
DataStore (Context.datastore を意味します) の作成にプロパティ デリゲートを使用していないため、DataStore オブジェクトにアクセスするたびに、DataStore オブジェクトがシングルトンであることが保証されません。
このシナリオを回避するには、テスト ケースごとにデータストアを削除して再作成するという 1 つのアプローチがあることがわかりました。 DataStore を削除するには、次の手順を実行します。
@After
fun cleanup() {
File(testContext.filesDir, "datastore").deleteRecursively()
}
すべてのテストの前に、それを再作成します。
@Before
fun setup() {
dataStore = DataStoreFactory.create(
produceFile = {
testContext.dataStoreFile(TEST_DATA_STORE_FILE_NAME)
},
serializer = MyItemSerializer
)
}
完全な例を確認するには、ここにアクセスしてください。
この記事では、Proto DataStore をテストする方法の概要を示したいと思います。
2 つのテスト ケースについて説明しましたが、データストアとそこで構成したタイプに応じて、さらに多くのテスト ケースとシナリオを作成する必要があります。構成要素はそこにあるので、必要に応じてそれを調整するだけです。
無料でコーディングを学びましょう。 freeCodeCamp のオープンソース カリキュラムは、40,000 人以上の人々が開発者としての職に就くのに役立ちました。始めましょう
-
Android携帯でアプリケーションを見つけて起動するためのトップ5の方法
スマートフォンにはアプリがいくつありますか?調査によると、一般的なユーザーは毎月2〜3個のアプリをインストールしますが、これは時間の経過とともにかなりの量になります。ついに数えたところ、97個ありました。 しかし、あなたが持っているものとそれらがどこにあるかを追跡することは難しい場合があります。幸いなことに、Androidにはアプリを見つけて起動するための多くの賢い方法があります。これがあなたが試すのに最適な5つです。 1.ホーム画面を適切に使用する Androidでアプリを起動する最も簡単な方法は、ホーム画面を最大限に活用することです。 Androidは、スマートフォンにすべてがインスト
-
TWRP:カスタムAndroidリカバリの完全ガイド
Androidが重要である限り、Androidの改造はかなり前から重要でした。隠し機能のロックを解除するためにスマートフォンをルート化する場合でも、Androidの完全にカスタムビルドをインストールする場合でも、Androidスマートフォンを改造してさらに活用したい理由はたくさんあります。 しかし、これらのAndroid改造の取り組みのすべてではないにしても、ほとんどのバックボーンは、ソフトウェアの1つの重要な部分であるカスタムリカバリです。そしてTWRPはカスタムリカバリのゴールドスタンダードです。 今日は、TWRPとは何か、そしてTWRPで何ができるかについて簡単に説明します。 TW