Friday, August 12, 2022
HomeiOS DevelopmentTesting UIKit accessibility in unit assessments – Ole Begemann

Testing UIKit accessibility in unit assessments – Ole Begemann

I’m writing a customized progress view in UIKit:

My round progress view

One of many design objectives for the view is to be a drop-in substitute for UIProgressView. This implies it ought to mannequin UIProgressView’s API and habits as intently as doable. One vital facet of that is accessibility: ideally, my progress view must be indistinguishable from a system progress view to VoiceOver customers.

To this finish, I’d like to write down a unit check that fails when it finds a discrepancy between my view’s accessibility settings and people of a regular UIProgressView. Earlier than we write that check, although, we should always examine what UIProgressView’s accessibility properties truly are to ensure we see the right information:

/// Easy assessments for the accessibility properties of UIKit controls,
/// to show that the check setup is working.
class UIAccessibilityTests: XCTestCase {
  func testUIProgressViewAccessibility() {
    let progressView = UIProgressView()
    progressView.progress = 0.4

    XCTAssertEqual(progressView.accessibilityLabel, "Progress")
    XCTAssertEqual(progressView.accessibilityTraits, [.updatesFrequently])
    XCTAssertEqual(progressView.accessibilityValue, "40%")
    // Extra assertions ...

Relying on the surroundings during which this check is run, some or all of those assertions unexpectedly fail:

  • In a unit check goal for a framework, all assertions fail.
  • In a unit check goal for an iOS utility, solely the primary assertion (isAccessibilityElement) fails, the others move.

(And sure, I do know a number of the assertions are locale-dependent. In case your check app has localizations for different languages than English, you might have to configure the right language in your construct scheme when operating the check.)

Dominik Hauser discovered that we will make the primary assertion move by including the view to a visual window and giving it a non-zero body:

  func testUIProgressViewAccessibility() {
    let progressView = UIProgressView(body: (CGRect(x: 0, y: 0, width: 200, peak: 20)))
    progressView.progress = 0.4

    let window = UIWindow(body: CGRect(x: 0, y: 0, width: 400, peak: 400))

    XCTAssertEqual(progressView.accessibilityLabel, "Progress")
    /// ...

Thanks lots for the assistance, Dominik (and everybody else who replied to my query)!

To summarize, the necessities for testing UIKit’s accessibility properties in a unit check appear to be:

  1. Your check goal have to be hooked up to an app goal. The assessments don’t work in a unit check goal for a library/framework, presumably as a result of making a window seen has no impact when the assessments aren’t injected right into a operating app.

  2. Set a non-zero body on the view underneath check.

  3. Create a UIWindow (ideally additionally with a non-zero body, though this wasn’t related in my testing) and add the view to the window. Name window.makeKeyAndVisible.

I say “appear to be” as a result of I’m not sure the habits is 100% deterministic. Some views, like UILabel, don’t require the extra setup.

Extra importantly, I’ve seen my assessments fail at the least as soon as. When that occurred, properties like accessibilityLabel didn’t even return their appropriate values when logged to the console from the check app, not simply within the assessments. It was as if your complete accessibility system on the simulator was not operating. Attaching the Accessibility Inspector to the simulator as soon as appeared to repair the problem (possibly this prompted the accessibility system to restart), and I haven’t been capable of reproduce the issue since, even after a number of reboots. All the pieces seems to be working now.

My check surroundings: Xcode 11.4.1 with the iOS 13 simulator.



Please enter your comment!
Please enter your name here

Most Popular