Authors native mobile accessibility tests covering iOS (Accessibility Inspector, XCUITest `performAccessibilityAudit()` introduced in iOS 17, VoiceOver label/trait/hint verification) and Android (Espresso `AccessibilityChecks.enable()`, Accessibility Scanner, TalkBack traversal, `contentDescription` labelling) with WCAG-aligned checks for element labels, 44pt/48dp touch targets, contrast ratios, and focus order. Use when an iOS or Android app needs automated and manual accessibility test coverage beyond what `xcuitest-suite` or `espresso-suite` provide.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Extends the core AccessibilityChecks.enable() example in
../SKILL.md. Checks run automatically on any ViewActions action
and cover the acted-on view plus all descendant views (atf).
// app/build.gradle
dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.6.1'
}import androidx.test.espresso.accessibility.AccessibilityChecks
@RunWith(AndroidJUnit4::class)
class CheckoutAccessibilityTest {
init {
AccessibilityChecks.enable().setRunChecksFromRootView(true)
}
@Test
fun applyPromoCode() {
onView(withId(R.id.promo_field)).perform(typeText("WELCOME10"), closeSoftKeyboard())
onView(withId(R.id.apply_button)).perform(click())
// checks fire automatically on every perform()
}
}setRunChecksFromRootView(true) evaluates the whole hierarchy, not just the
interacted view (atf).
AccessibilityChecks.enable().apply {
setSuppressingResultMatcher(
allOf(
matchesCheck(TextContrastCheck::class.java),
matchesViews(withId(R.id.decorative_watermark))
)
)
}The matcher must satisfy both the check type and the specific view (atf).
Each interactive UI element should have a focusable area of at least 48dp x 48dp
(atgt). AccessibilityChecks validates this on every perform() call.
AccessibilityChecks (via the Accessibility Test Framework) checks these on every
perform() call (contrast):
Convey purpose, not visual detail (cd):
// Icon-only button: set contentDescription
Icon(
imageVector = Icons.Filled.Share,
contentDescription = stringResource(R.string.label_share)
)
// Decorative image: suppress from accessibility
Icon(
imageVector = Icons.Filled.Decoration,
contentDescription = null // TalkBack skips this element
)Text composables need no contentDescription; TalkBack reads text content automatically.Verify with Espresso:
onView(withId(R.id.share_button))
.check(matches(withContentDescription(R.string.label_share)))Enable via Settings > Accessibility > TalkBack > On, then (at):
Manual checklist:
AccessibilityChecks.enable(), setRunChecksFromRootView(true), setSuppressingResultMatcher(), per-action firing.contentDescription: purpose not visual detail, null for decorative, unique labels in lists.