滚动直到元素可见iOS UI自动化与xcode7

Cod*_*ass 34 objective-c ios xcode-ui-testing

因此,通过新的xcode更新,apple改进了我们进行UI测试的方式.在乐器中,我们使用java脚本函数"isVisible"来确定我们的目标元素是否可见.

我试图在目标c中复制这个,但我似乎无法找到相当于此的东西.我有一个表视图,一个原型单元格,上面有两个标签.这个原型单元可以重复使用50次.

我正在尝试滚动,直到最后一个单元格可见,我这样做:

if (![[[[[[XCUIApplication alloc] init].tables childrenMatchingType:XCUIElementTypeCell] matchingIdentifier:@"cell"] elementBoundByIndex:49].staticTexts[@"text"] exists]) {
        [[[[[[XCUIApplication alloc] init].tables childrenMatchingType:XCUIElementTypeCell] matchingIdentifier:@"cell"] elementBoundByIndex:0].staticTexts[@"text"] swipeUp];
}
Run Code Online (Sandbox Code Playgroud)

但是这不会滑动,因为加载视图时元素存在.请帮助因为这让我发疯.

Kád*_*ádi 49

您应该扩展XCUIElement的方法列表.第一个方法(scrollToElement:)将在tableView上调用,第二个扩展方法可帮助您确定元素是否在主窗口上.

extension XCUIElement {

    func scrollToElement(element: XCUIElement) {
        while !element.visible() {
            swipeUp()
        }
    }

    func visible() -> Bool {
        guard self.exists && !CGRectIsEmpty(self.frame) else { return false }
        return CGRectContainsRect(XCUIApplication().windows.elementBoundByIndex(0).frame, self.frame)
    }

}
Run Code Online (Sandbox Code Playgroud)

滚动代码应如下所示(例如滚动到最后一个单元格):

func testScrollTable() {
    let app = XCUIApplication()
    let table = app.tables.elementBoundByIndex(0)
    let lastCell = table.cells.elementBoundByIndex(table.cells.count-1)
    table.scrollToElement(lastCell)
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特3:

extension XCUIElement {
    func scrollToElement(element: XCUIElement) {
        while !element.visible() {
            swipeUp()
        }
    }

    func visible() -> Bool {
        guard self.exists && !self.frame.isEmpty else { return false }
        return XCUIApplication().windows.element(boundBy: 0).frame.contains(self.frame)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案可以滚动到所需的单元格:( (2认同)

小智 20

以前的所有答案都不是100%失败证明.我遇到的问题是swipeUp()有一个更大的偏移量,当我在视图端口中有元素时,我找不到停止滚动的方法.有时元素会因滚动过多而滚动,因此测试用例失败.但是我设法使用以下代码控制滚动.

/**
Scrolls to a particular element until it is rendered in the visible rect
- Parameter elememt: the element we want to scroll to
*/
func scrollToElement(element: XCUIElement)
{
    while element.visible() == false
    {
        let app = XCUIApplication()
        let startCoord = app.collectionViews.element.coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.5))
        let endCoord = startCoord.coordinateWithOffset(CGVector(dx: 0.0, dy: -262));
        startCoord.pressForDuration(0.01, thenDragToCoordinate: endCoord)
    }
}

func visible() -> Bool
{
    guard self.exists && self.hittable && !CGRectIsEmpty(self.frame) else
    {
        return false
    }

    return CGRectContainsRect(XCUIApplication().windows.elementBoundByIndex(0).frame, self.frame)
}
Run Code Online (Sandbox Code Playgroud)

注意:如果您的视图是基于tableview,请使用app.tables


Rya*_*anM 8

解决方案使用swipeUp()并且swipeDown()不理想,因为它们可能由于滑动的动量而可能滚过目标元素.经过多次搜索和挫折,我找到了一个神奇的方法XCUICoordinate:

func press(forDuration duration: TimeInterval, thenDragTo otherCoordinate: XCUICoordinate)
Run Code Online (Sandbox Code Playgroud)

所以我们可以这样做:

let topCoordinate = XCUIApplication().statusBars.firstMatch.coordinate(withNormalizedOffset: .zero)
let myElement = XCUIApplication().staticTexts["My Element"].coordinate(withNormalizedOffset: .zero)
// drag from element to top of screen (status bar)
myElement.press(forDuration: 0.1, thenDragTo: topCoordinate)
Run Code Online (Sandbox Code Playgroud)

至于检查某些东西是否可见,你想要isHittable与之结合使用exists.请参阅scrollDownToElement下面的扩展程序

这是一个方便的扩展,将滚动直到元素在屏幕上,然后将该元素滚动到屏幕的顶部:)

extension XCUIApplication {
    private struct Constants {
        // Half way accross the screen and 10% from top
        static let topOffset = CGVector(dx: 0.5, dy: 0.1)

        // Half way accross the screen and 90% from top
        static let bottomOffset = CGVector(dx: 0.5, dy: 0.9)
    }

    var screenTopCoordinate: XCUICoordinate {
        return windows.firstMatch.coordinate(withNormalizedOffset: Constants.topOffset)
    }

    var screenBottomCoordinate: XCUICoordinate {
        return windows.firstMatch.coordinate(withNormalizedOffset: Constants.bottomOffset)
    }

    func scrollDownToElement(element: XCUIElement, maxScrolls: Int = 5) {
        for _ in 0..<maxScrolls {
            if element.exists && element.isHittable { element.scrollToTop(); break }
            scrollDown()
        }
    }

    func scrollDown() {
        screenBottomCoordinate.press(forDuration: 0.1, thenDragTo: screenTopCoordinate)
    }
}

extension XCUIElement {
    func scrollToTop() {
        let topCoordinate = XCUIApplication().screenTopCoordinate
        let elementCoordinate = coordinate(withNormalizedOffset: .zero)

        // Adjust coordinate so that the drag is straight up, otherwise
        // an embedded horizontal scrolling element will get scrolled instead
        let delta = topCoordinate.screenPoint.x - elementCoordinate.screenPoint.x
        let deltaVector = CGVector(dx: delta, dy: 0.0)

        elementCoordinate.withOffset(deltaVector).press(forDuration: 0.1, thenDragTo: topCoordinate)
    }
}
Run Code Online (Sandbox Code Playgroud)

通过添加的方法来点击这里scrollUp


And*_*rey 1

你可以这样做:

extension XCUIElement {
    internal func scrollToElement(element: XCUIElement) {
        while !element.exists {
            swipeDown()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用scrollToElement来查找元素