Xcode UI 测试 - UI 测试失败 - 点击搜索字段“取消”按钮时无法滚动到可见(通过 AX 操作)
Xcode UI test - UI Testing Failure - Failed to scroll to visible (by AX action) when tap on Search field "Cancel' button
我正在尝试通过点击搜索栏中的 'Cancel' 按钮关闭搜索字段。
测试用例找不到取消按钮。它在 Xcode 7.0.1
中运行良好
我添加了等待按钮出现的谓词。当我们点击 "cancel" 按钮
时,测试用例失败
let button = app.buttons[“Cancel”]
let existsPredicate = NSPredicate(format: "exists == 1")
expectationForPredicate(existsPredicate, evaluatedWithObject: button, handler: nil)
waitForExpectationsWithTimeout(5, handler: nil)
button.tap() // Failing here
日志:
t = 7.21s Tap SearchField
t = 7.21s Wait for app to idle
t = 7.29s Find the SearchField
t = 7.29s Snapshot accessibility hierarchy for com.test.mail
t = 7.49s Find: Descendants matching type SearchField
t = 7.49s Find: Element at index 0
t = 7.49s Wait for app to idle
t = 7.55s Synthesize event
t = 7.84s Wait for app to idle
t = 8.97s Type 'vinayak@xmd.net' into
t = 8.97s Wait for app to idle
t = 9.03s Find the "Search" SearchField
t = 9.03s Snapshot accessibility hierarchy for com.test.mail
t = 9.35s Find: Descendants matching type SearchField
t = 9.35s Find: Element at index 0
t = 9.36s Wait for app to idle
t = 9.42s Synthesize event
t = 10.37s Wait for app to idle
t = 10.44s Check predicate `exists == 1` against object `"Cancel" Button`
t = 10.44s Snapshot accessibility hierarchy for com.test.mail
t = 10.58s Find: Descendants matching type Button
t = 10.58s Find: Elements matching predicate '"Cancel" IN identifiers'
t = 10.58s Tap "Cancel" Button
t = 10.58s Wait for app to idle
t = 10.64s Find the "Cancel" Button
t = 10.64s Snapshot accessibility hierarchy for com.test.mail
t = 10.78s Find: Descendants matching type Button
t = 10.78s Find: Elements matching predicate '"Cancel" IN identifiers'
t = 10.79s Wait for app to idle
t = 11.08s Synthesize event
t = 11.13s Scroll element to visible
t = 11.14s Assertion Failure: UI Testing Failure - Failed to scroll to visible (by AX action) Button 0x7f7fcaebde40: traits: 8589934593, {{353.0, 26.0}, {53.0, 30.0}}, label: 'Cancel', error: Error -25204 performing AXAction 2003
我猜这里是 hittable
属性 的“取消”按钮 returns false
,这会阻止它点击。
如果您在文档中看到 tap()
,它会显示
/*!
* Sends a tap event to a hittable point computed for the element.
*/
- (void)tap;
似乎 Xcode 7.1 出了问题。为了让我自己(还有你 ;))不受这些问题的影响,我在 XCUIElement
上写了一个扩展,允许点击一个元素,即使它是不可点击的。以下可以帮到你。
/*Sends a tap event to a hittable/unhittable element.*/
extension XCUIElement {
func forceTapElement() {
if self.hittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinateWithNormalizedOffset(CGVectorMake(0.0, 0.0))
coordinate.tap()
}
}
}
现在你可以调用
button.forceTapElement()
更新 - 对于 Swift 3 使用以下内容:
extension XCUIElement {
func forceTapElement() {
if self.isHittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinate(withNormalizedOffset: CGVector(dx:0.0, dy:0.0))
coordinate.tap()
}
}
}
对我来说,根本原因是我想要点击的对象
- 已设置为隐藏(并返回)
- 已删除并重新附加
在这两种情况下,isAccessibilityElement
属性 之后都是 false
。将其设置回 true
修复它。
请检查元素的特征,我在使用 TableViewSectionHeader 时遇到了同样的问题,我试图点击但每次都失败
在我的例子中,它有一个以编程方式添加的 UI 元素覆盖按钮。
如果您使用 AppCenter 模拟器 运行 进行测试,您应该确保 运行 在与本地模拟器相同的设备版本上进行测试。我因此失去了 3 天的工作。
This question ranks well for Google queries around the term "Failed to scroll to visible (by AX action) Button". Given the age of the question I was inclined to think this was no longer an issue with the XCUITest framework as the accepted answer suggests.
我发现这个问题是由于 XCElement
存在,但隐藏在软件键盘后面。该错误是由框架发出的,因为它无法将存在的视图滚动到可点击的视图中。在我的例子中,有问题的按钮在软件键盘后面有时。
我发现 iOS 模拟器的软件键盘在某些情况下(例如:在您的机器上)可能会关闭,而在其他情况下(例如:在您的 CI 上)可能会打开。在我的例子中,我在一台机器上关闭了软件键盘,默认情况下它在其他机器上打开。
解决方案:在尝试点击键盘后面的按钮之前关闭键盘。
我发现在点击按钮之前点击某处明确关闭键盘解决了我在所有环境中的问题。
我添加了一些操作来让当前响应者 resignFirstResponder。我的文本视图背后的视图将迫使第一响应者辞职,所以我点击最后一个文本区域下方的某个地方。
/// The keyboard may be up, dismiss it by tapping just below the password field
let pointBelowPassword = passwordSecureTextField.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1))
pointBelowPassword.press(forDuration: 0.1)
Sandy 的变通方法在一段时间内似乎有帮助,但后来就没用了 - 然后我将其更改为:
func waitAndForceTap(timeout: UInt32 = 5000) {
XCTAssert(waitForElement(timeout: timeout))
coordinate(withNormalizedOffset: CGVector(dx:0.5, dy:0.5)).tap()
}
要点是因为问题是 isHittable 检查抛出异常,所以我根本不做这个检查,找到元素后直接找坐标。
本着可以覆盖您的元素的精神,我将 RN 调试器部分覆盖在我的图标之上:
试试这个:
if !button.isHittable {
let coordinate: XCUICoordinate = button.coordinate(withNormalizedOffset: CGVector(dx:0.0, dy:0.0))
coordinate.tap()
}
我正在尝试通过点击搜索栏中的 'Cancel' 按钮关闭搜索字段。
测试用例找不到取消按钮。它在 Xcode 7.0.1
中运行良好我添加了等待按钮出现的谓词。当我们点击 "cancel" 按钮
时,测试用例失败let button = app.buttons[“Cancel”]
let existsPredicate = NSPredicate(format: "exists == 1")
expectationForPredicate(existsPredicate, evaluatedWithObject: button, handler: nil)
waitForExpectationsWithTimeout(5, handler: nil)
button.tap() // Failing here
日志:
t = 7.21s Tap SearchField
t = 7.21s Wait for app to idle
t = 7.29s Find the SearchField
t = 7.29s Snapshot accessibility hierarchy for com.test.mail
t = 7.49s Find: Descendants matching type SearchField
t = 7.49s Find: Element at index 0
t = 7.49s Wait for app to idle
t = 7.55s Synthesize event
t = 7.84s Wait for app to idle
t = 8.97s Type 'vinayak@xmd.net' into
t = 8.97s Wait for app to idle
t = 9.03s Find the "Search" SearchField
t = 9.03s Snapshot accessibility hierarchy for com.test.mail
t = 9.35s Find: Descendants matching type SearchField
t = 9.35s Find: Element at index 0
t = 9.36s Wait for app to idle
t = 9.42s Synthesize event
t = 10.37s Wait for app to idle
t = 10.44s Check predicate `exists == 1` against object `"Cancel" Button`
t = 10.44s Snapshot accessibility hierarchy for com.test.mail
t = 10.58s Find: Descendants matching type Button
t = 10.58s Find: Elements matching predicate '"Cancel" IN identifiers'
t = 10.58s Tap "Cancel" Button
t = 10.58s Wait for app to idle
t = 10.64s Find the "Cancel" Button
t = 10.64s Snapshot accessibility hierarchy for com.test.mail
t = 10.78s Find: Descendants matching type Button
t = 10.78s Find: Elements matching predicate '"Cancel" IN identifiers'
t = 10.79s Wait for app to idle
t = 11.08s Synthesize event
t = 11.13s Scroll element to visible
t = 11.14s Assertion Failure: UI Testing Failure - Failed to scroll to visible (by AX action) Button 0x7f7fcaebde40: traits: 8589934593, {{353.0, 26.0}, {53.0, 30.0}}, label: 'Cancel', error: Error -25204 performing AXAction 2003
我猜这里是 hittable
属性 的“取消”按钮 returns false
,这会阻止它点击。
如果您在文档中看到 tap()
,它会显示
/*!
* Sends a tap event to a hittable point computed for the element.
*/
- (void)tap;
似乎 Xcode 7.1 出了问题。为了让我自己(还有你 ;))不受这些问题的影响,我在 XCUIElement
上写了一个扩展,允许点击一个元素,即使它是不可点击的。以下可以帮到你。
/*Sends a tap event to a hittable/unhittable element.*/
extension XCUIElement {
func forceTapElement() {
if self.hittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinateWithNormalizedOffset(CGVectorMake(0.0, 0.0))
coordinate.tap()
}
}
}
现在你可以调用
button.forceTapElement()
更新 - 对于 Swift 3 使用以下内容:
extension XCUIElement {
func forceTapElement() {
if self.isHittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinate(withNormalizedOffset: CGVector(dx:0.0, dy:0.0))
coordinate.tap()
}
}
}
对我来说,根本原因是我想要点击的对象
- 已设置为隐藏(并返回)
- 已删除并重新附加
在这两种情况下,isAccessibilityElement
属性 之后都是 false
。将其设置回 true
修复它。
请检查元素的特征,我在使用 TableViewSectionHeader 时遇到了同样的问题,我试图点击但每次都失败
在我的例子中,它有一个以编程方式添加的 UI 元素覆盖按钮。
如果您使用 AppCenter 模拟器 运行 进行测试,您应该确保 运行 在与本地模拟器相同的设备版本上进行测试。我因此失去了 3 天的工作。
This question ranks well for Google queries around the term "Failed to scroll to visible (by AX action) Button". Given the age of the question I was inclined to think this was no longer an issue with the XCUITest framework as the accepted answer suggests.
我发现这个问题是由于 XCElement
存在,但隐藏在软件键盘后面。该错误是由框架发出的,因为它无法将存在的视图滚动到可点击的视图中。在我的例子中,有问题的按钮在软件键盘后面有时。
我发现 iOS 模拟器的软件键盘在某些情况下(例如:在您的机器上)可能会关闭,而在其他情况下(例如:在您的 CI 上)可能会打开。在我的例子中,我在一台机器上关闭了软件键盘,默认情况下它在其他机器上打开。
解决方案:在尝试点击键盘后面的按钮之前关闭键盘。
我发现在点击按钮之前点击某处明确关闭键盘解决了我在所有环境中的问题。
我添加了一些操作来让当前响应者 resignFirstResponder。我的文本视图背后的视图将迫使第一响应者辞职,所以我点击最后一个文本区域下方的某个地方。
/// The keyboard may be up, dismiss it by tapping just below the password field
let pointBelowPassword = passwordSecureTextField.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1))
pointBelowPassword.press(forDuration: 0.1)
Sandy 的变通方法在一段时间内似乎有帮助,但后来就没用了 - 然后我将其更改为:
func waitAndForceTap(timeout: UInt32 = 5000) {
XCTAssert(waitForElement(timeout: timeout))
coordinate(withNormalizedOffset: CGVector(dx:0.5, dy:0.5)).tap()
}
要点是因为问题是 isHittable 检查抛出异常,所以我根本不做这个检查,找到元素后直接找坐标。
本着可以覆盖您的元素的精神,我将 RN 调试器部分覆盖在我的图标之上:
试试这个:
if !button.isHittable {
let coordinate: XCUICoordinate = button.coordinate(withNormalizedOffset: CGVector(dx:0.0, dy:0.0))
coordinate.tap()
}