Chris
Chris

Reputation: 3817

iOS UI testing - UILabel *with* accessibilityIdentifier cannot be found

I have a UIViewController subclass with a corresponding view designed in interface builder. In interface builder, I've set an accessibility identifier on two labels and Accessibility as a feature is enabled for both.

I want to define my app flow in code, so I load the VC by let vc = storyboard.instantiateViewController(withIdentifier: storyboardIdentifier) as? MyVC rather than by defining segues in IB.

In viewDidLoad, I can confirm that .accessibilityIdentifier is set.

And yet, in my tests, the elements cannot be found. This always returns false:

let app = XCUIApplication()
app.staticTexts["myIdentifier"].waitForExistence(timeout: 10)

If I then go on to print out the view hierarchy:

print(app.debugDescription)

 →Application, 0x280e55960, pid: 1609, label: 'My App'
    Window (Main), 0x280e55a40, {{0.0, 0.0}, {320.0, 568.0}}
      Other, 0x280e55c00, {{0.0, 0.0}, {320.0, 568.0}}
        NavigationBar, 0x280e55ce0, {{0.0, 20.0}, {320.0, 44.0}}, identifier: 'Thing'
          Button, 0x280e55ea0, {{0.0, 20.0}, {62.0, 44.0}}, label: 'Back'
          Other, 0x280e55f80, {{130.5, 32.0}, {59.5, 20.5}}, label: 'Thing'
        Other, 0x280e56060, {{0.0, 0.0}, {320.0, 568.0}}
          Other, 0x280e56140, {{0.0, 0.0}, {320.0, 568.0}}
            Other, 0x280e56220, {{0.0, 0.0}, {320.0, 568.0}}
              Other, 0x280e56300, {{0.0, 64.0}, {320.0, 504.0}}
                Image, 0x280e563e0, {{0.0, 248.0}, {320.0, 320.0}}, identifier: 'imageName'

I didn't set the identifier on Image - UIImage(named: "imageName") has done that automatically. The labels of interest are descendants of a sibling of the Image (i.e. grandchildren of Other, 0x280e56300)

I've read various guides (1, 2) and believe I'm doing everything as I should, and yet the elements remain hidden to the test framework.

Edited to add:

Since the app being tested is in a separate process, I added a UIAlertController to confirm the .accessibilityIdentifier of the labels of interest when their parent view appears in the context of being driven by the UI test mechanism - they are definitely set, but the testing framework just can't see them.

Upvotes: 3

Views: 4210

Answers (2)

j.rich
j.rich

Reputation: 44

I ran into a similar issue after embedding a text field and UILabel into a stack view using the hierarchy tree in the document outline. Doing this resulted in the UILabel accessibility label returning nil even though it had a value. If I set its accessibility label programmatically then it returned a value.

Also, if I added a new UILabel (and set its accessibility label) to the storyboard, outside the stackview, and then built the app both UILabels had values for their accessibility labels. I could then remove the second UILabel without the original UILabel losing its accessibility label.

Hopefully, this makes sense. It's one of my first posts.

Upvotes: 0

Chris
Chris

Reputation: 3817

Having painstakingly recreated the view step by step, confirming that elements could be found by their .accessibilityIdentifier at every step along the way, it was the final wrapping in a UIStackView that "broke" things.

That is, while everything worked with this view hierarchy:

+ View
  Safe Area
  + View
    + Stack view
      Label
      Label (with identifier)
    + Stack view
      Label
      Label (with identifier)
  Image View

Wrapping the plain view and image view in another stackview to achieve this:

+ View
  Safe Area
  + Stack view      <-- problematic stack view
    + View
      + Stack view
        Label
        Label (with identifier)
      + Stack view
        Label
        Label (with identifier)
    Image View

... broke things. Backtracking one step and achieving the same wrapping in a different way did not break accessibility.

Broke: Selecting View and Image View in the view hierarchy tree, then choosing embed in stackview from the icon in the editor pane.

Did not break: Selecting View and Image View in the designer and then choosing embed in stackview from the icon in the editor pane.

I realise this is a very anecdotal answer (and having lost more than half a day to this I've no intention of going back to break it again!), but it seems the way in which views are selected prior to embedding in a stack view makes a difference.

Upvotes: 4

Related Questions