Accessibility testing
Skill almasumdev/awesome-mobile-testing-agent-skills/.github/skills/ui/accessibility-testing
Expert guidance on automated and manual accessibility testing for mobile apps — Espresso AccessibilityChecks, XCTest accessibility audits, Flutter a11y guidelines, RN a11y assertions. Use when adding a11y coverage or when asked how to catch accessibility regressions in CI.From its SKILL.md
npx -y skills add almasumdev/awesome-mobile-testing-agent-skills --skill accessibility-testingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.2 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
Accessibility Testing
Instructions
Accessibility bugs are defects, not polish items. A tap target that is 24 dp square, an icon button with no content description, or a form field unreachable by VoiceOver is a shipped regression. Cover them with automated checks in CI plus a small set of manual heuristics for each critical flow.
1. What Automation Can Catch
Automated scanners reliably catch:
- Missing content descriptions / accessibility labels on interactive elements.
- Contrast ratios below WCAG AA for known text colors.
- Touch targets below the platform minimum (48 dp Android, 44 pt iOS).
- Duplicate or confusing focus order (platform-dependent).
- Form fields without labels.
They do not catch: whether the label makes sense, whether the reading order is logical, whether animations trigger vestibular issues. That is the manual pass.
2. Android — Espresso / Compose
Enable AccessibilityChecks for the whole suite:
@BeforeClass @JvmStatic fun enableA11yChecks() {
AccessibilityChecks.enable().setRunChecksFromRootView(true)
}
For Compose, use SemanticsMatcher and assertContentDescriptionEquals:
composeRule.onNodeWithTag("pay")
.assertContentDescriptionEquals("Pay 19.99 USD")
.assert(hasClickAction())
For Views, AccessibilityNodeInfo assertions are surfaced automatically by AccessibilityChecks — a failing check fails the test.
3. iOS — XCTest Accessibility Audit
iOS 17+ ships a native accessibility audit:
func test_checkout_isAccessible() throws {
let app = XCUIApplication(); app.launch()
app.buttons["openCheckout"].tap()
try app.performAccessibilityAudit() // fails on any violation
}
Scope audits per screen, not per entire app launch — failures are easier to read. For SwiftUI unit-level checks, assert .accessibilityLabel, .accessibilityHint, and .accessibilityTraits on the rendered view hierarchy.
4. Flutter — flutter_test Guidelines
testWidgets('Checkout meets tap-target guidelines', (tester) async {
await tester.pumpWidget(const AppShell(child: CheckoutScreen()));
final handle = tester.ensureSemantics();
await expectLater(tester, meetsGuideline(androidTapTargetGuideline));
await expectLater(tester, meetsGuideline(iOSTapTargetGuideline));
await expectLater(tester, meetsGuideline(textContrastGuideline));
await expectLater(tester, meetsGuideline(labeledTapTargetGuideline));
handle.dispose();
});
Use Semantics(label: ...) wrappers in production code for icon-only widgets.
5. React Native
import { render } from '@testing-library/react-native';
test('Pay button has accessible label', () => {
const { getByRole } = render(<CheckoutScreen />);
const btn = getByRole('button', { name: /pay/i });
expect(btn).toBeTruthy();
expect(btn.props.accessibilityLabel).toBeDefined();
});
For contrast and tap size, rely on design-system tokens that enforce minimums at build time, plus a periodic manual sweep — RN does not have a first-class runtime a11y auditor.
6. Manual Heuristics
For every critical flow, before release:
- Screen reader sweep. Enable TalkBack / VoiceOver; complete the flow without looking at the screen. Every focusable element must announce a meaningful label.
- Dynamic type. Set the OS text size to the largest supported; verify no clipped labels, truncated buttons, or overlapping views.
- Contrast. Spot-check with a contrast checker on non-token surfaces (marketing screens, onboarding).
- Keyboard / switch control (iPadOS, Android with keyboard). The app must be usable without touch on large-screen surfaces.
- Reduce motion. Turn on "Reduce motion" / "Remove animations"; make sure the flow still works and is not disorienting.
7. Linting at Build Time
- Android Lint rules:
ContentDescription,LabelFor,ClickableViewAccessibility. - SwiftLint / custom rule to forbid
Image(systemName:)inside aButtonwithout.accessibilityLabel. - Dart:
flutter analyze+ custom lints (missing_contentdescription-style rules viadart_code_metrics). - RN:
eslint-plugin-react-native-a11y.
Enable these in CI so regressions fail before tests even run.
8. Reporting Violations
Upload the a11y audit JSON (Android) / audit output (iOS) as a CI artifact. When a test fails, the report must name: element, rule, and how to fix (content description / larger target / higher contrast).
9. Checklist
-
AccessibilityChecks.enable()/performAccessibilityAudit()/ Flutter guideline expectations wrap every UI test suite. - Icon-only buttons have labels enforced by lint, not code review.
- Dynamic type, screen reader, and reduce-motion manual sweeps are documented per critical flow.
- Contrast is tested at the design-token level, not on every screen.
- Platform-minimum tap targets (48 dp / 44 pt) are enforced.
- A11y violations fail the build the same as functional test failures.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.