Categories
iOS Swift SwiftUI

Performing accessibility audits with UI tests on iOS

A new way how to test your app’s accessibility was added in iOS 17. XCUIApplication has a new method, performAccessibilityAudit. It has two arguments where the first is audit types which is by default set to all. The second argument is an issue handler, and we can use if for filtering out any false positives. Let’s see what are the different audit types. Audit types are listed under XCUIAccessibilityAuditType type: contrast, elementDetection, hitRegion, sufficientElementDescription, dynamicType, textClipped, and trait.

Since I recently released my app Silky Brew, then let’s see how to set up the accessibility auditing with UI-tests.

final class AccessibilityAuditTests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
func testBeansListAccessibility() throws {
let app = XCUIApplication()
app.launchEnvironment["SBOnboardingVisibility"] = "-1"
app.launchEnvironment["SBSkipsAnimations"] = "1"
app.launchEnvironment["SBUsesPreviewData"] = "1"
app.launch()
try app.performAccessibilityAudit()
}
}

The test sets some environment keys which are used by the app to reconfigure some of its state. In the example above, we turn off onboarding view, speed up animations, and enable custom data (pre-defined user content). Here we can see how the test is running.

The accessibility audit did not come back without issues. One of the issues was a hitRegion problem. Report navigator shows more information about the failure.

After some trial and error, I found the issue triggering it. Not sure why, but the performAccessibilityAudit function failed to catch the element triggering the issue. Fortunately, accessibility indicator was able to pinpoint the element without a problem. So seems like if UI-tests catch accessibility issues but fail to highlight elements, then we can still go back to accessibility indicator for finding these. The particular issue was with the row view which shows several lines of text and two of these labels were using footnote and caption text styles. This in turn made text labels smaller and triggered the hitRegion error.

VStack(alignment: .leading) {
Text(beans.name)
Text("by \(beans.roastery)")
.font(.footnote)
.foregroundStyle(.secondary)
if let grindLabel {
Divider()
Text(grindLabel)
.font(.caption)
.foregroundStyle(.secondary)
}
}
view raw RowView.swift hosted with ❤ by GitHub

Since the row view is just multiple lines of text, then we can make it easier for accessibility users to read by combining all the text labels into one by adding .accessibilityElement(children: .combine) to the VStack. This solved that particular issue.

If this was helpful, please let me know on Mastodon@toomasvahter or Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.