Xcode UITest 有时找不到 属性 XCUIElement
Xcode UITest sometimes does not find property of XCUIElement
在我的 UI 测试中,找到了一些 XCUIElement
的框架 属性,但没有找到其他框架。
下面使用的可访问性标识符在故事板中设置,并且 app
在 setUp()
中初始化为 XCUIApplication()
。
这是故事板布局:
测试中使用的两个 UI 元素是 Text Field 和 Add Button。
相关代码如下:
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)")
}
测试在倒数第二行的错误断点处停止,并显示以下消息:
No matches found for Find: Descendants matching type TextField from input {(
Application, 0x60000019f070, pid: 13114, label: ‚xxx‘
)}
我不明白为什么在第一种情况下找到了应该为所有XCUIElement
定义的frame
属性,而在第二种情况下却找不到。
编辑
Oletha 在下面指出,我的常量 addShoppingItemTextField
是一个 XCUIElementQuery
,当我尝试读取 [=26] 的 frame
属性 时应该解决这个问题=].
事实上,当程序在测试错误断点处停止并且我打印它的描述时,我得到
Printing description of addShoppingItemTextField:
Query chain:
→Find: Target Application 0x6080000a6ea0
↪︎Find: Descendants matching type TextField
↪︎Find: Elements matching predicate '"TextField" IN identifiers'
但是查找失败,尽管辅助功能已启用,并且辅助功能标识符设置为 TextField
:
我也在app里插入了
print(textField.accessibilityIdentifier!)
在viewDidLoad()
中,它正确地打印出TextField
。
作为解决方法,我将测试设置为录音,然后点击 textField
。这为访问 textField
创建了代码。然后我把 let addShoppingItemTextField = app.textFields["TextField"]
换成了(右边是录音生成的):
let addShoppingItemTextField = app.otherElements.containing(.navigationBar, identifier:"WatchNotOK")
.children(matching: .other).element.children(matching: .other).element
.children(matching: .other).element
现在代码可以正常运行了。
所以在我看来,对 textField
的可访问性标识符的查询无法正常工作。
编辑 2
我放弃:在不更改故事板中的任何内容的情况下,测试现在停止并出现相同的测试错误(未找到查找的匹配项:元素匹配谓词'"WatchNotOK" IN 标识符') 在行 let navBarHeight = mainViewNavigationBar.frame.size.height
。这确实一直有效。
这向我表明 Xcode UI 测试已损坏。
问题不是没有在元素上找到 frame
属性,而是找不到元素本身。
每个 XCUIElement
都派生自一个 XCUIElementQuery
。第一次尝试解决查询并不是像您预期的那样,当您分配 addShoppingItemTextField
的值时,而是您第一次访问 属性(不同于 exists
)时 addShoppingItemTextField
.
因此,当您尝试访问 XCUIElement
对象上的 frame
属性 时,查找该元素的查询已解决,但未找到该元素 - 所以您在访问 frame
的行中收到错误消息 'No matches found...'。这可能有点误导,但您遇到的问题是找不到该元素。尝试调整您的查询。
我联系了 Apple,他们发现了我的错误:
我的主视图控制器的视图将其 accessibility
属性 设置为 true
。这是错误的;它 必须 设置为 false
:
解释见docs至isAccessibilityElement
:
此 属性 的默认值为 false,除非接收器是标准 UIKit 控件,在这种情况下值为 true。
辅助应用程序只能获取有关由可访问性元素表示的对象的信息。因此,如果您实现了应该可供残障用户访问的自定义控件或视图,请将此 属性 设置为 true。这种做法的唯一例外是视图仅用作其他应该可访问的项目的容器。这样的视图应该实现 UIAccessibilityContainer 协议并将此 属性 设置为 false。
一旦我将主视图的可访问性设置为 false,UI 测试就成功了。
除了上面的回答...我想补充一点
这可能是因为 您正在访问的 XCUIElement 在屏幕 上不可用。
假设您正在为登录屏幕执行测试用例,并且模拟器正在使用仪表板而不是登录屏幕启动。这发生在我的案子上。我试图注销然后执行测试用例。错误消失
在我的 UI 测试中,找到了一些 XCUIElement
的框架 属性,但没有找到其他框架。
下面使用的可访问性标识符在故事板中设置,并且 app
在 setUp()
中初始化为 XCUIApplication()
。
这是故事板布局:
测试中使用的两个 UI 元素是 Text Field 和 Add Button。
相关代码如下:
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)")
}
测试在倒数第二行的错误断点处停止,并显示以下消息:
No matches found for Find: Descendants matching type TextField from input {(
Application, 0x60000019f070, pid: 13114, label: ‚xxx‘
)}
我不明白为什么在第一种情况下找到了应该为所有XCUIElement
定义的frame
属性,而在第二种情况下却找不到。
编辑
Oletha 在下面指出,我的常量 addShoppingItemTextField
是一个 XCUIElementQuery
,当我尝试读取 [=26] 的 frame
属性 时应该解决这个问题=].
事实上,当程序在测试错误断点处停止并且我打印它的描述时,我得到
Printing description of addShoppingItemTextField:
Query chain:
→Find: Target Application 0x6080000a6ea0
↪︎Find: Descendants matching type TextField
↪︎Find: Elements matching predicate '"TextField" IN identifiers'
但是查找失败,尽管辅助功能已启用,并且辅助功能标识符设置为 TextField
:
我也在app里插入了
print(textField.accessibilityIdentifier!)
在viewDidLoad()
中,它正确地打印出TextField
。
作为解决方法,我将测试设置为录音,然后点击 textField
。这为访问 textField
创建了代码。然后我把 let addShoppingItemTextField = app.textFields["TextField"]
换成了(右边是录音生成的):
let addShoppingItemTextField = app.otherElements.containing(.navigationBar, identifier:"WatchNotOK")
.children(matching: .other).element.children(matching: .other).element
.children(matching: .other).element
现在代码可以正常运行了。
所以在我看来,对 textField
的可访问性标识符的查询无法正常工作。
编辑 2
我放弃:在不更改故事板中的任何内容的情况下,测试现在停止并出现相同的测试错误(未找到查找的匹配项:元素匹配谓词'"WatchNotOK" IN 标识符') 在行 let navBarHeight = mainViewNavigationBar.frame.size.height
。这确实一直有效。
这向我表明 Xcode UI 测试已损坏。
问题不是没有在元素上找到 frame
属性,而是找不到元素本身。
每个 XCUIElement
都派生自一个 XCUIElementQuery
。第一次尝试解决查询并不是像您预期的那样,当您分配 addShoppingItemTextField
的值时,而是您第一次访问 属性(不同于 exists
)时 addShoppingItemTextField
.
因此,当您尝试访问 XCUIElement
对象上的 frame
属性 时,查找该元素的查询已解决,但未找到该元素 - 所以您在访问 frame
的行中收到错误消息 'No matches found...'。这可能有点误导,但您遇到的问题是找不到该元素。尝试调整您的查询。
我联系了 Apple,他们发现了我的错误:
我的主视图控制器的视图将其 accessibility
属性 设置为 true
。这是错误的;它 必须 设置为 false
:
解释见docs至isAccessibilityElement
:
此 属性 的默认值为 false,除非接收器是标准 UIKit 控件,在这种情况下值为 true。
辅助应用程序只能获取有关由可访问性元素表示的对象的信息。因此,如果您实现了应该可供残障用户访问的自定义控件或视图,请将此 属性 设置为 true。这种做法的唯一例外是视图仅用作其他应该可访问的项目的容器。这样的视图应该实现 UIAccessibilityContainer 协议并将此 属性 设置为 false。
一旦我将主视图的可访问性设置为 false,UI 测试就成功了。
除了上面的回答...我想补充一点 这可能是因为 您正在访问的 XCUIElement 在屏幕 上不可用。 假设您正在为登录屏幕执行测试用例,并且模拟器正在使用仪表板而不是登录屏幕启动。这发生在我的案子上。我试图注销然后执行测试用例。错误消失