UITesting Xcode 7: как узнать, виден ли XCUIElement?

Я автоматизирую приложение с помощью тестирования пользовательского интерфейса в Xcode 7. У меня есть прокрутка с XCUIElements (включая кнопки и т. Д.) На всем пути вниз. Иногда XCUIElements видны, иногда они скрыты слишком далеко вверх или вниз по прокрутке (в зависимости от того, где я нахожусь в прокрутке).

Есть ли способ прокрутить элементы в поле зрения или, может быть, сказать, видны они или нет?

Спасибо


person Charlie Seligman    schedule 01.10.2015    source источник


Ответы (5)


К сожалению, Apple не предоставила метод scrollTo или параметр .visible для XCUIElement. Тем не менее, вы можете добавить пару вспомогательных методов для реализации некоторых из этих функций. Вот как я это сделал в 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 возвращает true, если элемент был загружен, но не отображается на экране. Кроме того, мы должны проверить, что у целевого элемента есть кадр больше 0 на 0 (иногда это тоже верно) — тогда мы можем проверить, находится ли этот кадр в главном окне.

Затем нам нужен метод для прокрутки контролируемой суммы вверх или вниз:

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)
    }
}  

Изменение значений CGVector для topScreenPoint и bottomScreenPoint изменит масштаб действия прокрутки — имейте в виду, что если вы подойдете слишком близко к краям экрана, вы вытащите одно из меню ОС.

Используя эти два метода, вы можете написать цикл, который прокручивается до заданного порога в одну сторону, пока элемент не станет видимым, а затем, если он не находит свою цель, он прокручивается в другую сторону:

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 без пороговой логики. Надеюсь это поможет!

person Tucker Sherman    schedule 05.11.2015
comment
Это работает, но мне пришлось получить главное окно, используя другой подход: func mainWindow() -> XCUIElement { return XCUIApplication().windows.elementBoundByIndex(0) } Кроме того, то, что вы назвали 'scrollUp', более традиционно называлось бы ' прокрутить вниз' - person isoiphone; 11.05.2016
comment
хорошие моменты isoiphone! что XCUIApplication.mainWindow() было расширением, которое я забыл добавить в этот пример кода, я отредактировал ответ, чтобы он был более полным, и для ясности поменял местами scrollUp и scrollDown. - person Tucker Sherman; 11.05.2016

Что мне нужно было сделать, чтобы решить эту проблему, так это провести пальцем вверх или вниз по коду тестирования пользовательского интерфейса. Вы пробовали это?

XCUIApplication().swipeUp()

Или вы также можете сделать WhateverUIElement.swipUp(), и он будет прокручиваться вверх/вниз по отношению к этому элементу.

Надеюсь, они исправят функцию автоматической прокрутки или автоматического поиска, чтобы нам не пришлось делать это вручную.

person Narine Cholakian    schedule 25.10.2015
comment
Привет, Нарине. Да, я делаю swipeUp() и вниз, но не могу узнать, когда элемент находится в поле зрения.. :-( Как вы говорите, надеюсь, они придумают способ обойти это в будущем. - person Charlie Seligman; 26.10.2015

Вы должны проверить свойство isHittable.

Если представление не скрыто, соответствующий XCUIElement доступен для попадания. Но есть предостережение. «Вид 1» может перекрываться «Видом 2», но элемент, соответствующий «Виду 1», может быть доступен для попадания.

person Sergey Dunets    schedule 28.03.2016

Поскольку у вас есть некоторые XCUIElements в нижней части табличного представления (представление нижнего колонтитула таблицы), способ прокрутки табличного представления до конца в тесте пользовательского интерфейса, предполагая, что в вашем табличном представлении много данных, - это tap().

.swipeUp() также выполняет свою работу, но проблема в том, что когда ваши тестовые данные огромны, прокрутка занимает целую вечность, в отличие от .tap(), который напрямую переходит в нижнюю часть tableView.

Более конкретно:

XCUIElementsInTheBottomOrTableFooterView.tap()
XCTAssert(XCUIElementsInTheBottomOrTableFooterView.isHittable, "message") 
person TunaTheDog    schedule 21.09.2017

Похоже, это известная ошибка :-(

https://forums.developer.apple.com/thread/9934

person Charlie Seligman    schedule 02.10.2015