UITesting Xcode 7:如何判断XCUIElement是否可见?
UITesting Xcode 7: How to tell if XCUIElement is visible?
我正在使用 UI 测试在 Xcode 7 中自动化应用程序。我有一个带有 XCUI 元素(包括按钮等)的滚动视图。有时 XCUI 元素是可见的,有时它们在滚动视图的上方或下方隐藏得太远(取决于我在滚动视图中的位置)。
有没有办法将项目滚动到视图中或者判断它们是否可见?
谢谢
看起来这是一个已知错误:-(
我必须做的是在我的 UI 测试代码中实际向上或向下滑动来解决这个问题。你试过这个吗?
XCUIApplication().swipeUp()
或者您也可以执行 WhateverUIElement.swipUp(),它会相对于该元素滚动 up/down。
希望他们能修复自动滚动或自动查找功能,这样我们就不必手动执行此操作。
遗憾的是,Apple 未在 XCUIElement
上提供任何 scrollTo
方法或 .visible
参数。也就是说,您可以添加几个辅助方法来实现其中的一些功能。这是我在 Swift.
中的做法
首先检查元素是否可见:
func elementIsWithinWindow(element: XCUIElement) -> Bool {
guard element.exists && !CGRectIsEmpty(element.frame) && element.hittable else { return false }
return CGRectContainsRect(XCUIApplication().windows.elementBoundByIndex(0).frame, element.frame)
}
不幸的是 .exists
returns 如果元素已加载但不在屏幕上则为真。此外,我们必须检查目标元素是否有一个比 0 大 0 的框架(有时也是如此)——然后我们可以检查这个框架是否在主 window.
内
然后我们需要一种方法来向上或向下滚动可控量:
func scrollDown(times: Int = 1) {
let topScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
bottomScreenPoint.pressForDuration(0, thenDragToCoordinate: topScreenPoint)
}
}
func scrollUp(times: Int = 1) {
let topScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
topScreenPoint.pressForDuration(0, thenDragToCoordinate: bottomScreenPoint)
}
}
更改 topScreenPoint 和 bottomScreenPoint 的 CGVector 值将更改滚动操作的比例 - 请注意,如果您离屏幕边缘太近,您将拉出 OS 菜单之一。
使用这两种方法,您可以编写一个循环,以一种方式滚动到给定阈值,直到元素变得可见,然后如果它找不到目标,则以另一种方式滚动:
func scrollUntilElementAppears(element: XCUIElement, threshold: Int = 10) {
var iteration = 0
while !elementIsWithinWindow(element) {
guard iteration < threshold else { break }
scrollDown()
iteration++
}
if !elementIsWithinWindow(element) { scrollDown(threshold) }
while !elementIsWithinWindow(element) {
guard iteration > 0 else { break }
scrollUp()
iteration--
}
}
最后一种方法效率不高,但至少可以让您找到屏幕外的元素。当然,如果您知道您的目标元素在给定测试中总是会高于或低于您的起点,您可以只编写 scrollDownUntil
或 scrollUpUntill
方法,而无需此处的阈值逻辑。
希望这对您有所帮助!
Swift 5 次更新
func elementIsWithinWindow(element: XCUIElement) -> Bool {
guard element.exists && !element.frame.isEmpty && element.isHittable else { return false }
return XCUIApplication().windows.element(boundBy: 0).frame.contains(element.frame)
}
func scrollDown(times: Int = 1) {
let mainWindow = app.windows.firstMatch
let topScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
bottomScreenPoint.press(forDuration: 0, thenDragTo: topScreenPoint)
}
}
func scrollUp(times: Int = 1) {
let mainWindow = app.windows.firstMatch
let topScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
topScreenPoint.press(forDuration: 0, thenDragTo: bottomScreenPoint)
}
}
func scrollUntilElementAppears(element: XCUIElement, threshold: Int = 10) {
var iteration = 0
while !elementIsWithinWindow(element: element) {
guard iteration < threshold else { break }
scrollDown()
iteration += 1
}
if !elementIsWithinWindow(element: element) {
scrollDown(times: threshold)
}
while !elementIsWithinWindow(element: element) {
guard iteration > 0 else { break }
scrollUp()
iteration -= 1
}
}
您应该检查 isHittable
属性。
如果view没有被隐藏,对应的XCUIElement是可命中的。但有一个警告。 "View 1"可以被"View 2"重叠,但是"View 1"对应的元素是可以命中的
由于您在 table 视图(table 页脚视图)底部有一些 XCUI 元素,因此滚动 table 查看所有UI 测试底部的方法,假设您的 table 视图有很多数据,是 tap()
.
.swipeUp()
也可以,但问题是当你的测试数据很大时,滑动需要永远,而不是 .tap()
直接跳到底部 table查看。
更具体地说:
XCUIElementsInTheBottomOrTableFooterView.tap()
XCTAssert(XCUIElementsInTheBottomOrTableFooterView.isHittable, "message")
我正在使用 UI 测试在 Xcode 7 中自动化应用程序。我有一个带有 XCUI 元素(包括按钮等)的滚动视图。有时 XCUI 元素是可见的,有时它们在滚动视图的上方或下方隐藏得太远(取决于我在滚动视图中的位置)。
有没有办法将项目滚动到视图中或者判断它们是否可见?
谢谢
看起来这是一个已知错误:-(
我必须做的是在我的 UI 测试代码中实际向上或向下滑动来解决这个问题。你试过这个吗?
XCUIApplication().swipeUp()
或者您也可以执行 WhateverUIElement.swipUp(),它会相对于该元素滚动 up/down。
希望他们能修复自动滚动或自动查找功能,这样我们就不必手动执行此操作。
遗憾的是,Apple 未在 XCUIElement
上提供任何 scrollTo
方法或 .visible
参数。也就是说,您可以添加几个辅助方法来实现其中的一些功能。这是我在 Swift.
首先检查元素是否可见:
func elementIsWithinWindow(element: XCUIElement) -> Bool {
guard element.exists && !CGRectIsEmpty(element.frame) && element.hittable else { return false }
return CGRectContainsRect(XCUIApplication().windows.elementBoundByIndex(0).frame, element.frame)
}
不幸的是 .exists
returns 如果元素已加载但不在屏幕上则为真。此外,我们必须检查目标元素是否有一个比 0 大 0 的框架(有时也是如此)——然后我们可以检查这个框架是否在主 window.
然后我们需要一种方法来向上或向下滚动可控量:
func scrollDown(times: Int = 1) {
let topScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
bottomScreenPoint.pressForDuration(0, thenDragToCoordinate: topScreenPoint)
}
}
func scrollUp(times: Int = 1) {
let topScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = app.mainWindow().coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
topScreenPoint.pressForDuration(0, thenDragToCoordinate: bottomScreenPoint)
}
}
更改 topScreenPoint 和 bottomScreenPoint 的 CGVector 值将更改滚动操作的比例 - 请注意,如果您离屏幕边缘太近,您将拉出 OS 菜单之一。
使用这两种方法,您可以编写一个循环,以一种方式滚动到给定阈值,直到元素变得可见,然后如果它找不到目标,则以另一种方式滚动:
func scrollUntilElementAppears(element: XCUIElement, threshold: Int = 10) {
var iteration = 0
while !elementIsWithinWindow(element) {
guard iteration < threshold else { break }
scrollDown()
iteration++
}
if !elementIsWithinWindow(element) { scrollDown(threshold) }
while !elementIsWithinWindow(element) {
guard iteration > 0 else { break }
scrollUp()
iteration--
}
}
最后一种方法效率不高,但至少可以让您找到屏幕外的元素。当然,如果您知道您的目标元素在给定测试中总是会高于或低于您的起点,您可以只编写 scrollDownUntil
或 scrollUpUntill
方法,而无需此处的阈值逻辑。
希望这对您有所帮助!
Swift 5 次更新
func elementIsWithinWindow(element: XCUIElement) -> Bool {
guard element.exists && !element.frame.isEmpty && element.isHittable else { return false }
return XCUIApplication().windows.element(boundBy: 0).frame.contains(element.frame)
}
func scrollDown(times: Int = 1) {
let mainWindow = app.windows.firstMatch
let topScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
bottomScreenPoint.press(forDuration: 0, thenDragTo: topScreenPoint)
}
}
func scrollUp(times: Int = 1) {
let mainWindow = app.windows.firstMatch
let topScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.05))
let bottomScreenPoint = mainWindow.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.90))
for _ in 0..<times {
topScreenPoint.press(forDuration: 0, thenDragTo: bottomScreenPoint)
}
}
func scrollUntilElementAppears(element: XCUIElement, threshold: Int = 10) {
var iteration = 0
while !elementIsWithinWindow(element: element) {
guard iteration < threshold else { break }
scrollDown()
iteration += 1
}
if !elementIsWithinWindow(element: element) {
scrollDown(times: threshold)
}
while !elementIsWithinWindow(element: element) {
guard iteration > 0 else { break }
scrollUp()
iteration -= 1
}
}
您应该检查 isHittable
属性。
如果view没有被隐藏,对应的XCUIElement是可命中的。但有一个警告。 "View 1"可以被"View 2"重叠,但是"View 1"对应的元素是可以命中的
由于您在 table 视图(table 页脚视图)底部有一些 XCUI 元素,因此滚动 table 查看所有UI 测试底部的方法,假设您的 table 视图有很多数据,是 tap()
.
.swipeUp()
也可以,但问题是当你的测试数据很大时,滑动需要永远,而不是 .tap()
直接跳到底部 table查看。
更具体地说:
XCUIElementsInTheBottomOrTableFooterView.tap()
XCTAssert(XCUIElementsInTheBottomOrTableFooterView.isHittable, "message")