Compose アプリは、確立されたアプローチとパターンでテストできます。
単独でのテスト
ComposeTestRule
を使用すると、任意のコンポーザブル(アプリケーション全体、単一の画面、小さな要素など)を表示するアクティビティを開始できます。また、コンポーザブルが正しくカプセル化され、独立して動作することを確認することもおすすめします。これにより、UI テストをより簡単かつ集中できます。
これは、単体 UI テストのみを作成するということではありません。UI テストでは、UI の大きな部分にスコープ設定することも非常に重要です。
独自のコンテンツの設定後にアクティビティとリソースにアクセスする
多くの場合、composeTestRule.setContent
を使用してテスト対象のコンテンツを設定する必要があり、アクティビティ リソースにアクセスする必要もあります。たとえば、表示されるテキストが文字列リソースに一致することをアサートします。ただし、アクティビティがすでに setContent
を呼び出している場合、createAndroidComposeRule()
で作成したルールに対してまた呼び出すことはできません。
これを実現するための一般的なパターンは、ComponentActivity
などの空のアクティビティを使用して AndroidComposeTestRule
を作成することです。
class MyComposeTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun myTest() {
// Start the app
composeTestRule.setContent {
MyAppTheme {
MainScreen(uiState = exampleUiState, /*...*/)
}
}
val continueLabel = composeTestRule.activity.getString(R.string.next)
composeTestRule.onNodeWithText(continueLabel).performClick()
}
}
アプリの AndroidManifest.xml
ファイルに ComponentActivity
を追加する必要があるのでご注意ください。そのためには、次の依存関係をモジュールに追加します。
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
カスタム セマンティクス プロパティ
カスタム セマンティクス プロパティを作成して、テストに情報を公開できます。作成するには、新しい SemanticsPropertyKey
を定義し、SemanticsPropertyReceiver
を使用して利用可能にします。
// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey
このプロパティを semantics
修飾子で使用します。
val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
modifier = Modifier.semantics { pickedDate = datePickerValue }
)
テストでは、SemanticsMatcher.expectValue
を使用してプロパティの値をアサートします。
composeTestRule
.onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
.assertExists()
状態の復元を検証する
アクティビティまたはプロセスを再作成する場合、Compose 要素の状態が正しく復元されていることを検証します。StateRestorationTester
クラスを使用すると、アクティビティの再作成に依存せずに、こうしたチェックを行えます。
このクラスを使用すると、コンポーザブルの再作成をシミュレートできます。特に、rememberSaveable
の実装を検証するのに便利です。
class MyStateRestorationTests {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun onRecreation_stateIsRestored() {
val restorationTester = StateRestorationTester(composeTestRule)
restorationTester.setContent { MainScreen() }
// TODO: Run actions that modify the state
// Trigger a recreation
restorationTester.emulateSavedInstanceStateRestore()
// TODO: Verify that state has been correctly restored.
}
}
さまざまなデバイス構成をテストする
Android アプリは、ウィンドウ サイズ、ロケール、フォントサイズ、ダークモードとライトモードなど、変化するさまざまな条件に適応する必要があります。これらの条件のほとんどは、ユーザーが制御するデバイスレベルの値から派生し、現在の Configuration
インスタンスで公開されます。テストで異なる構成を直接テストするのは難しいです。これは、テストでデバイスレベルのプロパティを構成する必要があるためです。
DeviceConfigurationOverride
はテスト専用の API で、テスト対象の @Composable
コンテンツに対して、ローカライズされた方法でさまざまなデバイス構成をシミュレートできます。
DeviceConfigurationOverride
のコンパニオン オブジェクトには、デバイスレベルの構成プロパティをオーバーライドする次の拡張機能があります。
DeviceConfigurationOverride.DarkMode()
: システムをダークモードまたはライトモードにオーバーライドします。DeviceConfigurationOverride.FontScale()
: システム フォント スケールをオーバーライドします。DeviceConfigurationOverride.FontWeightAdjustment()
: システム フォントの太さの調整をオーバーライドします。DeviceConfigurationOverride.ForcedSize()
: デバイスのサイズに関係なく、特定のスペースを強制的に確保します。DeviceConfigurationOverride.LayoutDirection()
: レイアウトの方向(左から右または右から左)をオーバーライドします。DeviceConfigurationOverride.Locales()
: ロケールをオーバーライドします。DeviceConfigurationOverride.RoundScreen()
: 画面が丸い場合のオーバーライド。
特定のオーバーライドを適用するには、テスト対象のコンテンツを DeviceConfigurationOverride()
トップレベル関数の呼び出しでラップし、適用するオーバーライドをパラメータとして渡します。
たとえば、次のコードは DeviceConfigurationOverride.ForcedSize()
オーバーライドを適用して密度をローカルで変更し、テストを実行しているデバイスがそのウィンドウ サイズを直接サポートしていない場合でも、MyScreen
コンポーザブルを強制的に大きな横向きのウィンドウでレンダリングします。
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } }
複数のオーバーライドを同時に適用するには、DeviceConfigurationOverride.then()
を使用します。
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } }
参考情報
- Android でアプリをテストする: Android テストのメイン ランディング ページでは、テストの基礎と手法について幅広く説明しています。
- テストの基礎: Android アプリのテストに関する基本コンセプトを学びます。
- ローカルテスト: 一部のテストは、自分のワークステーションでローカルに実行できます。
- インストルメンテーション テスト: インストルメンテーション テストも実行することをおすすめします。つまり、デバイス上で直接実行されるテストです。
- 継続的インテグレーション: 継続的インテグレーションを使用すると、テストをデプロイ パイプラインに統合できます。
- さまざまな画面サイズをテストする: ユーザーが利用できるデバイスが多いため、さまざまな画面サイズでテストする必要があります。
- Espresso: Espresso はビューベースの UI を対象としていますが、Compose テストの一部のアスペクトでも役立ちます。