mcpField
E
enabling-accessibility-checks

enabling-accessibility-checks

github.com/skydovesテスト・品質33967 回インストール22 週間前に更新
リポジトリ

enabling-accessibility-checks について

Jetpack Compose のテストで Espresso の AccessibilityValidator を有効にするスキルガイドです。Android の開発者向けに、API 34 以降の実機要件や Robolectric の制約を含め、アクセシビリティ回帰テストの方法を説明します。

主な機能

  1. 01Compose テストでチェックを有効化
  2. 02警告またはエラーのしきい値設定
  3. 03UI 変更操作の検証
  4. 04チェックの手動実行
  5. 05Espresso と検証器を共有

活用シーン

  1. 01Compose 画面のアクセシビリティ回帰テスト
  2. 02違反時にテストを失敗させる
  3. 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-75
  • ComposeTestRule オーバーロード — NotImplementedError:compose/ui/ui-test-junit4-accessibility/src/androidMain/kotlin/androidx/compose/ui/test/junit4/accessibility/ComposeTestRuleExt.android.kt:38-66
  • enableAccessibilityChecks(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

コメント