In my UI tests, the frame property of some XCUIElement
are found, but not of others.
The accessibility identifiers used below are set in storyboard, and app
is initialised in setUp()
as XCUIApplication()
.
Here is the storyboard layout:
The two UI elements used in the test are Text Field and Add Button.
Here is the relevant code:
func test() {
// given
let mainViewNavigationBar = app.navigationBars[„NavBar“]
let navBarHeight = mainViewNavigationBar.frame.size.height
print("navBarHeight: \(navBarHeight)") // is printed out correctly
let addShoppingItemTextField = app.textFields["TextField"]
let textFieldHeight = addShoppingItemTextField.frame.size.height // error breakpoint here
print("textFieldHeight: \(textFieldHeight)")
}
The test stops at an error breakpoint at the second last line with the following message:
No matches found for Find: Descendants matching type TextField from input {(
Application, 0x60000019f070, pid: 13114, label: ‚xxx‘
)}
I do not understand why the frame
property, which should be defined for all XCUIElement
, is found in the first case, but not in the second.
EDIT
Oletha pointed out below, that my constant addShoppingItemTextField
is an XCUIElementQuery
that should be resolved when I try to read the frame
property of the textField
.
Indeed, when the program stops at the test error breakpoint and I print its description, I get
Printing description of addShoppingItemTextField:
Query chain:
→Find: Target Application 0x6080000a6ea0
↪︎Find: Descendants matching type TextField
↪︎Find: Elements matching predicate '"TextField" IN identifiers'
But the find fails, although Accessibility is enabled, and the Accessibility Identifier is set to TextField
:
I also inserted in the app
print(textField.accessibilityIdentifier!)
in viewDidLoad()
, and it printed out TextField
correctly.
As a workaround, I set the test to recording, and tapped the textField
. This created code for the access to the textField
. I then replaced let addShoppingItemTextField = app.textFields["TextField"]
by (the right side was generated by the recording):
let addShoppingItemTextField = app.otherElements.containing(.navigationBar, identifier:"WatchNotOK")
.children(matching: .other).element.children(matching: .other).element
.children(matching: .other).element
And now the code works without errors.
So it seems to me that the query for the accessibility identifier of a textField
does not work correctly.
EDIT 2
I give up: Without changing anything in the storyboard, the test now stops with the same test error (No matches found for Find: Elements matching predicate '"WatchNotOK" IN identifiers‘) at the line let navBarHeight = mainViewNavigationBar.frame.size.height
. This did work all the time.
This indicates to me that Xcode UI tests are broken.
I contacted Apple, and they found my bug:
The view of my main view controller had its accessibility
property set to true
. This was wrong; it must be set to false
:
The explanation is found in the docs to isAccessibilityElement
:
The default value for this property is false unless the receiver is a standard UIKit control, in which case the value is true.
Assistive applications can get information only about objects that are represented by accessibility elements. Therefore, if you implement a custom control or view that should be accessible to users with disabilities, set this property to true. The only exception to this practice is a view that merely serves as a container for other items that should be accessible. Such a view should implement the UIAccessibilityContainer protocol and set this property to false.
As soon as I set accessibility of the main view to false, the UI test succeeded.