it-swarm.com.ru

Xcode7 | Xcode UI Тесты | Как обрабатывать оповещения службы определения местоположения?

Я пишу тестовые случаи пользовательского интерфейса для одного из моих приложений, используя XCUIApplication, XCUIElement и XCUIElementQuery, представленные в Xcode7/iOS 9.

Я столкнулся с дорожным блоком. Один из экранов в тестовом случае требует iOS Location Services. Как и ожидалось, пользователю предлагается разрешить использование службы определения местоположения с предупреждением под названием: Allow “App name” to access your location while you use the app? с кнопками Allow & Don't Allow

Проблема в том или ином, что кажется, что поскольку предупреждение представлено самой ОС, его нет в поддереве элементов приложения.

Я зарегистрировал следующее:

print("XYZ:\(app.alerts.count)")//0
var existence = app.staticTexts["Allow “App Name” to access your location while you use the app?"].exists
print("XYZ:\(existence)")//false
existence  = app.buttons["Allow"].exists
print("XYZ:\(existence)") //false

Даже запись пользовательского интерфейса генерирует похожий код:

XCUIApplication().alerts["Allow “App Name” to access your location while you use the app?"].collectionViews.buttons["Allow"].tap()

Я не нашел ни одного API, который бы помог мне справиться с этой проблемой. Например:

  • Нажмите на позицию на экране
  • Получать оповещения вне приложения

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

29
Taha

Xcode 9

    let springboard = XCUIApplication(bundleIdentifier: "com.Apple.springboard")
    let allowBtn = springboard.buttons["Allow"]
    if allowBtn.exists {
        allowBtn.tap()
    }

Xcode 8.3.3

    _ = addUIInterruptionMonitor(withDescription: "Location Dialog") { (alert) -> Bool in
        alert.buttons["Allow"].tap()
        return true
    }
    app.buttons["Request Location"].tap()
    app.tap() // need to interact with the app for the handler to fire

Обратите внимание, что это немного отличается, так как имя метода теперь addUIInterruptionMonitor и принимает withDescription в качестве аргумента

Xcode 7.1

Xcode 7.1 наконец исправил проблему с системными предупреждениями. Есть, однако, две маленькие ошибки.

Во-первых, вам нужно настроить «обработчик прерываний пользовательского интерфейса» перед тем, как представить предупреждение. Это наш способ рассказать фреймворку, как обрабатывать оповещение при его появлении.

Во-вторых, после подачи предупреждения вы должны взаимодействовать с интерфейсом. Простое нажатие на приложение работает просто отлично, но обязательно.

addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
    alert.buttons["Allow"].tap()
    return true
}

app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire

«Диалог местоположения» - это просто строка, помогающая разработчику определить, к какому обработчику обращались, он не относится к типу оповещения.

Xcode 7.0

Следующее отклонит единственное «системное предупреждение» в Xcode 7 Beta 6:

let app = XCUIApplication()
app.launch()
// trigger location permission dialog

app.alerts.element.collectionViews.buttons["Allow"].tap()

Бета 6 представила множество исправлений для UI Testing, и я считаю, что это был один из них.

Также обратите внимание, что я звоню -element непосредственно на -alerts. Вызов -element для XCUIElementQuery вынуждает каркас выбирать «один и только» соответствующий элемент на экране. Это прекрасно работает для оповещений, когда вы можете видеть только одно изображение за раз. Однако, если вы попробуете это для метки и будете иметь две метки, фреймворк вызовет исключение.

29
Joe Masilotti

Это было единственное, что сработало для меня. Используя Xcode 9 fwiw.

Также вероятно уместно, что я уже использовал addUIInterruptionMonitor для другого предупреждения. Я попытался изменить их порядок, и это не имело значения. Может быть, это проблема в 9, когда у вас есть два, или я неправильно их использовал. В любом случае приведенный ниже код работал. :)

let springboard = XCUIApplication(bundleIdentifier: "com.Apple.springboard")
let allowBtn = springboard.buttons["Allow"]
if allowBtn.exists {
    allowBtn.tap()
}
7
Joe Susnick

Если вы хотите проверить, отображается ли предупреждение, просто проверьте наличие кнопки:

if (app.alerts.element.collectionViews.buttons["Dismiss"].exists)
{
app.alerts.element.collectionViews.buttons["Dismiss"].tap()
}

он проверяет, отображается ли предупреждение, и если он показывает, он коснется его 

3
Joao_dche

Я заставил его работать с этим на Xcode 9.4.1 , трюк состоял в том, чтобы ждать появления всплывающего окна.

// wait for location service popup to appear
    let springboard = XCUIApplication(bundleIdentifier: "com.Apple.springboard")
    let allowBtn = springboard.buttons["Allow"]
    expectation(for: NSPredicate(format: "exists == true"), evaluatedWith: allowBtn, handler: nil)
    waitForExpectations(timeout: 10, handler: nil)

    //allow location service
    if allowBtn.exists {
      allowBtn.tap()
    }
3
null

В xcode 9.1 оповещения обрабатываются только в том случае, если на тестовом устройстве установлена ​​iOS 11. Не работает на старых версиях iOS, например 10.3 и т.д. Ссылка: https://forums.developer.Apple.com/thread/86989

Для обработки оповещений используйте это:

//Use this before the alerts appear. I am doing it before app.launch()

let allowButtonPredicate = NSPredicate(format: "label == 'Always Allow' || label == 'Allow'")
//1st alert
_ = addUIInterruptionMonitor(withDescription: "Allow to access your location?") { (alert) -> Bool in
    let alwaysAllowButton = alert.buttons.matching(allowButtonPredicate).element.firstMatch
    if alwaysAllowButton.exists {
        alwaysAllowButton.tap()
        return true
    }
    return false
}
//Copy paste if there are more than one alerts to handle in the app
2
Hasaan Ali

Это работает для всех языков:

        let springboard = XCUIApplication(bundleIdentifier: "com.Apple.springboard")
        let allowBtn = springboard.buttons.element(boundBy: 2)
        if allowBtn.exists {
            allowBtn.tap()
        }
1
Maciek z Wrocławia

Чтобы нажать «Разрешить оповещение о местоположении», вы можете вызвать Element.tap (), где element - любой элемент на вашем экране. Таким образом, после вызова нажмите, доступ будет касаться Разрешить по предупреждению, а затем нажмите на ваш элемент

0
Andrey