CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/mobile-a11y-test-author

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

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

android-checks.mdreferences/

Android accessibility test detail

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).

Add the dependency

// app/build.gradle
dependencies {
    androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.6.1'
}

Enable checks from the root view

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).

Suppress known issues

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).

Touch target size (48dp minimum)

Each interactive UI element should have a focusable area of at least 48dp x 48dp (atgt). AccessibilityChecks validates this on every perform() call.

Contrast thresholds

AccessibilityChecks (via the Accessibility Test Framework) checks these on every perform() call (contrast):

  • Text smaller than 18sp, or bold text smaller than 14sp: minimum contrast ratio 4.5:1.
  • All other text: minimum contrast ratio 3:1.

contentDescription labelling

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.
  • List items need distinct descriptions so a screen reader does not repeat the same label.

Verify with Espresso:

onView(withId(R.id.share_button))
    .check(matches(withContentDescription(R.string.label_share)))

TalkBack manual workflow

Enable via Settings > Accessibility > TalkBack > On, then (at):

  1. Linear navigation: swipe right/left through elements in order; double-tap to activate.
  2. Explore by touch: drag to hear elements under your finger.

Manual checklist:

  • All interactive elements are reachable via swipe.
  • Each element announces its purpose clearly and without redundancy.
  • Alert messages are announced when they appear.
  • Focus traversal order matches the visual reading order.

References

SKILL.md

tile.json