enabling-accessibility-checks について
Jetpack Compose のテストで Espresso の AccessibilityValidator を有効にするスキルガイドです。Android の開発者向けに、API 34 以降の実機要件や Robolectric の制約を含め、アクセシビリティ回帰テストの方法を説明します。
主な機能
- 01Compose テストでチェックを有効化
- 02警告またはエラーのしきい値設定
- 03UI 変更操作の検証
- 04チェックの手動実行
- 05Espresso と検証器を共有
活用シーン
- 01Compose 画面のアクセシビリティ回帰テスト
- 02違反時にテストを失敗させる
- 03Robolectric の判定が不確かな理由の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill enabling-accessibility-checksインストール後、Claude Code で/enabling-accessibility-checksを入力して読み込まれたか確認します。
詳細
アクセシビリティチェックを有効にする — Compose ツリーで Espresso の AccessibilityValidator を使用する
Compose のアクセシビリティテスト用アーティファクトは、Espresso の AccessibilityValidator(com.google.android.apps.common.testing.accessibility.framework.integrations.espresso にあるもの)を Compose のアクションパイプラインに組み込みます。有効にすると、UI を変更するすべてのアクション(performClick、performScrollTo*、performTextInput など)で、まず基盤となる View に対してバリデーターが実行されます。2 つのテストエントリーポイント(ComposeUiTest と ComposeTestRule)に対応する 2 種類のアーティファクトがあり、1 つは安定版、もう 1 つは実験版です。有意な結果を得るには、実機と API 34 以降が必要です。Robolectric ではバリデーターはインストールされますが、Log.w 警告が出力され、テストの合格は確定的なものではありません(Robolectric はアクセシビリティサービスを正確に動作させないためです)。
このスキルを使用する場合
- 開発者が Compose のみの画面にアクセシビリティのリグレッションテストを追加する場合。
- コントラスト、タッチターゲット、ラベルのルールに違反するとビルドが失敗する a11y テストを、レビュー担当者が求めている場合。
- 開発者が「AccessibilityChecks.enable」「AccessibilityValidator」または「Compose accessibility validator」に言及した場合。
- Compose と View を併用する画面で、Espresso と Compose の間で同じ
AccessibilityValidatorを共有する必要がある場合。 - 開発者の a11y チェックが Robolectric で何も行わないように見える場合(その理由は
Log.w警告で説明されます)。
このスキルを使用しない場合
- a11y 違反ではなく、不適切なファインダーが原因でチェックに失敗する場合。
../printing-the-semantics-tree/SKILL.mdを使用してください。 - テストが Robolectric(ホスト JVM)で実行される場合。制限については
compose/ui/ui-test-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/accessibility/ComposeUiTestExt.android.kt:50-53に記載されています。テストをandroidDeviceTestに移し、API 34 以降の実機で実行してください。詳しくは../../setup/setting-up-host-vs-device-tests/SKILL.mdを参照してください。 - テスト対象 API が 34 未満の場合。アノテーション
@RequiresApi(34)により、minSdk が低いとコンパイルエラーになります。テストメソッドに@SdkSuppress(minSdkVersion = 34)を使用し、それより古いデバイスではテストをスキップしてください。 - ユーザーがセマンティクスのテスト(ロール、コンテンツ説明、クリックアクション)を求めている場合。
../../assertions/asserting-node-state-and-text/SKILL.mdを使用してください。
前提条件
- API 34+(Android U)を実行する実 Android デバイス(またはエミュレーター)。
- 次のいずれか:
androidTestImplementationにandroidx.compose.ui:ui-test-accessibilityを追加 —ComposeUiTestを拡張します。@RequiresApi(34) @ExperimentalTestApiが必要です。@OptIn(ExperimentalTestApi::class)も必要です。androidTestImplementationにandroidx.compose.ui:ui-test-junit4-accessibilityを追加 —AndroidComposeTestRuleとComposeTestRuleを拡張します。必要なのは@RequiresApi(34)のみです。実験版ではありません。
../../patterns/structuring-a-compose-test/SKILL.mdにあるテストクラスのひな形。
ワークフロー
- 1. テストごとに(または
@Beforeで)一度だけチェックを有効にします。AndroidComposeTestRuleの API:
import androidx.compose.ui.test.junit4.accessibility.enableAccessibilityChecks
import com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator
@Before
fun before() {
rule.enableAccessibilityChecks() // default: AccessibilityValidator().setRunChecksFromRootView(true)
}
デフォルトバリデーターのシグネチャ。参照先:compose/ui/ui-test-junit4-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/junit4/accessibility/AndroidComposeTestRuleExt.android.kt:44-49:
@RequiresApi(34)
public fun <R : TestRule, A : ComponentActivity> AndroidComposeTestRule<R, A>.enableAccessibilityChecks(
accessibilityValidator: AccessibilityValidator =
AccessibilityValidator().setRunChecksFromRootView(true),
)
ComposeUiTest の場合(たとえば runComposeUiTest { } の内部)、同等の API は androidx.compose.ui.test.accessibility にあり、@OptIn(ExperimentalTestApi::class) が必要です:
@OptIn(ExperimentalTestApi::class)
@Test
fun runs() = runAndroidComposeUiTest<ComponentActivity> {
enableAccessibilityChecks()
onNodeWithText("Submit").performClick()
}
参照元:compose/ui/ui-test-accessibility/samples/src/main/java/androidx/compose/ui/test/accessibility/samples/AccessibilityChecksSamples.kt:42-61。
- 2.
AccessibilityValidator自体を使って、より厳格なモードを設定します。 カスタムバリデーターを渡して、しきい値を警告のみからエラーに切り替えます。
val validator = AccessibilityValidator().apply {
setThrowExceptionFor(AccessibilityCheckResultType.ERROR)
}
rule.enableAccessibilityChecks(validator)
参照元:AccessibilityChecksSamples.kt:68-82。
-
3. UI を変更する各操作の前に、自動チェックが実行されます。 参照先:
compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt:79, 160, 189, 236, 402, 451, 496, 535, 697, 780, 948—performClick、performScrollTo、performScrollToIndex/Key/Node、performTouchInput、performMouseInput、performKeyInput、performTrackpadInput、performRotaryScrollInput、performIndirectPointerInput、performFirstLinkClick、およびテキスト操作群の先頭でtryPerformAccessibilityChecks()が呼び出されます。performMultiModalInputでは自動チェックは実行されません(Actions.kt:582)。開発者がtryPerformAccessibilityChecks()を明示的に呼び出す必要があります。requestFocus()(Actions.kt:600-601)はperformSemanticsActionを経由し、同様に自動チェックは実行されません。その場合のアクセシビリティテストが重要であれば、フォーカス後にtryPerformAccessibilityChecks()を呼び出してください。 -
4. 必要に応じて手動でチェックを実行します(
performMultiModalInputの場合、またはフェーズの開始条件にする場合)。
rule.onRoot().tryPerformAccessibilityChecks()
参照元:AccessibilityChecksSamples.kt:53。
- 5. Compose と View を組み合わせた画面では、バリデーターを Espresso と共有します。
AccessibilityChecks.enable()は Espresso が使用するものと同じバリデーターインスタンスを返します。Compose に渡すことで、両方のレイヤーで同一の設定を使ってレポートできます。
import androidx.test.espresso.accessibility.AccessibilityChecks
@OptIn(ExperimentalTestApi::class)
@Test
fun hybrid() = runAndroidComposeUiTest<ComponentActivity> {
val validator = AccessibilityChecks.enable()
enableAccessibilityChecks(validator)
}
参照元:AccessibilityChecksSamples.kt:88-98。
- 6. 分離されたフェーズを終了するときは、チェックを無効にします。
rule.disableAccessibilityChecks()
参照先:AndroidComposeTestRuleExt.android.kt:71-75。
- 7.
ComposeTestRuleオーバーロードを使うのは、ルールが実際にAndroidComposeTestRuleである場合に限ります。 参照先:compose/ui/ui-test-junit4-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/junit4/accessibility/ComposeTestRuleExt.android.kt:38-49。Android 以外のルールではNotImplementedErrorがスローされます:
Enabling accessibility checks is currently only supported for AndroidComposeTestRule.
If you have a custom ComposeTestRule implementation that wraps an AndroidComposeTestRule,
directly call enableAccessibilityChecks on the AndroidComposeTestRule instead
パターン
パターン:Robolectric で有効にする — 結果は確定的ではありません
// WRONG (assertion is meaningless under Robolectric)
@Config(sdk = [34])
@RunWith(RobolectricTestRunner::class)
class MyA11yTest {
@get:Rule val rule = createComposeRule(StandardTestDispatcher())
@Test fun checks() {
rule.enableAccessibilityChecks() // logs Log.w; validator IS installed
rule.setContent { /* contrast violation */ }
rule.onNodeWithTag("submit").performClick() // may PASS, may FAIL — inconclusive
}
}
// WRONG because: HasRobolectricFingerprint = (Build.FINGERPRINT.lowercase() == "robolectric")
// triggers a Log.w but the validator is STILL installed (ComposeUiTestExt.android.kt:50-61
// AND AndroidComposeTestRuleExt.android.kt:50-64). Robolectric does not faithfully drive
// the accessibility services, so any result is inconclusive. Tracking bug: b/332778271.
// Run accessibility checks ONLY on a real device API 34+ for trustworthy results.
// RIGHT — move the test to androidDeviceTest and run on a real device API 34+
@MediumTest
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = 34)
class MyA11yTest {
@get:Rule val rule = createComposeRule(StandardTestDispatcher())
@Before fun before() { rule.enableAccessibilityChecks() }
@Test fun submitPassesA11y() {
rule.setContent { MyScreen() }
rule.onNodeWithTag("submit").performClick()
}
}
パターン:performMultiModalInput では自動チェックがスキップされます
// WRONG
@Test
fun multiModal() {
rule.enableAccessibilityChecks()
rule.setContent { MyScreen() }
rule.onNodeWithTag("canvas").performMultiModalInput {
touch { down(center); up() }
key { pressKey(Key.Enter) }
}
// No a11y check ran for this action — Actions.kt:582 omits tryPerformAccessibilityChecks().
}
// RIGHT
@Test
fun multiModal() {
rule.enableAccessibilityChecks()
rule.setContent { MyScreen() }
rule.onNodeWithTag("canvas").performMultiModalInput { … }
rule.onRoot().tryPerformAccessibilityChecks() // explicit
}
パターン:ComposeTestRule(Android 以外)のオーバーロードでは例外がスローされます
// WRONG
val rule: ComposeTestRule = MyCustomRuleThatWrapsAndroid()
rule.enableAccessibilityChecks() // throws NotImplementedError
// WRONG because: only AndroidComposeTestRule is supported. Cited at
// ComposeTestRuleExt.android.kt:38-49.
// RIGHT — call on the underlying AndroidComposeTestRule
val rule = AndroidComposeTestRule(/* … */)
rule.enableAccessibilityChecks()
パターン:Espresso とバリデーターを共有する
// RIGHT
@OptIn(ExperimentalTestApi::class)
@Test
fun shared() = runAndroidComposeUiTest<ComponentActivity> {
val validator = AccessibilityChecks.enable().apply {
setThrowExceptionFor(AccessibilityCheckResultType.ERROR)
}
enableAccessibilityChecks(validator)
onNodeWithText("Submit").performClick()
}
必須ルール
- 必須:
enableAccessibilityChecksを呼び出すテストでは、実機の API 34 以降を対象にしてください。Robolectric でチェックが意味のある結果を返すことを前提にしてはなりません。Build.FINGERPRINT.lowercase() == "robolectric"の場合、Log.w("...", "Accessibility checks are currently not supported by Robolectric")が出力されます(ComposeUiTestExt.android.kt:50-53、AndroidComposeTestRuleExt.android.kt:50-56)。バリデーターはインストールされますが、Robolectric が忠実にエミュレートしないアクセシビリティサービスに依存することはできません。Robolectric でテストが成功しても、判定不能として扱ってください。追跡バグ:b/332778271。 - 必須:ルールのエントリーポイントを使う場合は、安定版の
androidx.compose.ui:ui-test-junit4-accessibilityを優先してください。ComposeUiTestに対してandroidx.compose.ui:ui-test-accessibilityを使う場合は、必ず@OptIn(ExperimentalTestApi::class)を適用してください。 - 必須:これらの操作に対する検証を行う場合は、
performMultiModalInput { … }の後、およびrequestFocus()の後に、手動でtryPerformAccessibilityChecks()を呼び出してください。Actions.kt:582ではperformMultiModalInputの自動チェックが省略されており、requestFocus()(Actions.kt:600-601)はperformSemanticsActionを経由するため、こちらも自動チェックされません。 - 禁止:
AndroidComposeTestRuleでもあるComposeTestRule以外に対してenableAccessibilityChecksを呼び出さないでください。Android 以外のオーバーロードはNotImplementedErrorをスローします(ComposeTestRuleExt.android.kt:38-49)。 - 推奨:違反をログに記録するだけでなくテスト失敗とするため、
AccessibilityValidator().setThrowExceptionFor(...)でしきい値をAccessibilityCheckResultType.ERRORに設定してください。 - 推奨:Compose と Views を組み合わせたテストスイートでは、
AccessibilityChecks.enable()を使ってAccessibilityValidatorを 1 つ共有し、Espresso と Compose の両方に渡してください。参照:AccessibilityChecksSamples.kt:88-98。
検証
- テストが実機の API 34 以降で実行されます。モジュールの minSdk が 34 未満の場合は、
@SdkSuppress(minSdkVersion = 34)が指定されています。 - テスト出力に Robolectric の
Log.w警告「Accessibility checks are currently not supported by Robolectric」が表示されません。 - 該当するアーティファクトが
androidTestImplementationに含まれています。ルール経由の場合はandroidx.compose.ui:ui-test-junit4-accessibility、ComposeUiTest経由の場合はandroidx.compose.ui:ui-test-accessibilityと@OptIn(ExperimentalTestApi::class)です。 -
enableAccessibilityChecks(...)がテストごとに 1 回(または@Before内で)呼び出されます。disableAccessibilityChecks()は、意図的にチェックを抑制する場合にのみ呼び出されます。 -
performMultiModalInput { … }を呼び出す箇所の後に、明示的にrule.onRoot().tryPerformAccessibilityChecks()を呼び出しています。 - Compose と View を組み合わせたテストスイートでは、
AccessibilityChecks.enable()を使ってバリデーターを取得し、enableAccessibilityChecks(validator)に渡しています。 -
AndroidComposeTestRule以外のインスタンスに対してenableAccessibilityChecksを呼び出していません。
参照
enableAccessibilityChecks(ルールのパス):compose/ui/ui-test-junit4-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/junit4/accessibility/AndroidComposeTestRuleExt.android.kt:44-75ComposeTestRuleオーバーロード — NotImplementedError:compose/ui/ui-test-junit4-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/junit4/accessibility/ComposeTestRuleExt.android.kt:38-66enableAccessibilityChecks(ComposeUiTest のパス):compose/ui/ui-test-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/accessibility/ComposeUiTestExt.android.kt:44-77- Robolectric で結果が確定しない場合の動作(警告を出し、バリデーターは引き続きインストール):
ComposeUiTestExt.android.kt:50-61、AndroidComposeTestRuleExt.android.kt:50-64、b/332778271 Actions.ktでの自動チェックの呼び出し箇所:compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt:79, 160, 189, 236, 402, 451, 496, 535, 582 (omitted), 697, 780, 948- サンプル:
compose/ui/ui-test-accessibility/samples/src/main/java/androidx/compose/ui/test/accessibility/samples/AccessibilityChecksSamples.kt:42-98 - Espresso のアクセシビリティチェック:https://developer.android.com/training/testing/espresso/accessibility-checking
- アクセシビリティのテスト(Compose):https://developer.android.com/develop/ui/compose/accessibility/testing
- Compose UI テストのリリースノート:https://developer.android.com/jetpack/androidx/releases/compose-ui