Xcode7 | Тесты интерфейса Xcode | Как справиться с оповещением о местоположении?
Я пишу тестовые примеры для одного из моих приложений, используя XCUIApplication, XCUIElement и XCUIElementQuery, представленные в Xcode7/iOS 9.
Я попал в дорожный блок. Один из экранов в тестовом случае требует службы местоположения iOS. Как и ожидалось, пользователю будет предложено разрешить использование службы определения местоположения с предупреждением под заголовком: 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, который может заставить меня пройти мимо этой проблемы. Например:
- Нажмите в позиции на экране
- Получить оповещения вне приложения
Итак, как я могу пройти мимо этого? Есть ли способ настроить тестовые цели, чтобы не разрешать авторизацию службы геопозиционирования.
Ответы
Ответ 1
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
заставляет платформу выбрать "один-единственный" соответствующий элемент на экране. Это прекрасно работает для оповещений, когда вы можете видеть только одно изображение за раз. Однако, если вы попробуете это для метки и у вас будет две метки, фреймворк вызовет исключение.
Ответ 2
Это единственное, что сработало для меня. Использование Xcode 9 fwiw.
Также возможно, что я уже использовал addUIInterruptionMonitor
для другого оповещения. Я попробовал переупорядочить их, и это не изменило ситуацию. Может быть, это проблема в 9, когда у вас есть две, или я могу использовать их неправильно. В любом случае код ниже работал.:)
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons["Allow"]
if allowBtn.exists {
allowBtn.tap()
}
Ответ 3
Если вы хотите проверить, отображается ли предупреждение, просто проверьте наличие кнопки:
if (app.alerts.element.collectionViews.buttons["Dismiss"].exists)
{
app.alerts.element.collectionViews.buttons["Dismiss"].tap()
}
он проверяет, отображается ли предупреждение, и если он показывает его, он коснется его
Ответ 4
Я заставил это работать с этим на 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()
}
Ответ 5
В 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
Ответ 6
Это работает для всех языков:
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons.element(boundBy: 1)
if allowBtn.exists {
allowBtn.tap()
}
Ответ 7
Чтобы разрешить доступ к предупреждению о местоположении, вы можете позвонить
element.tap(), где элемент - это любой элемент на вашем экране.
Таким образом, после вызова нажмите, доступ будет нажать "Разрешить на предупреждение", а затем коснуться вашего элемента
Ответ 8
Вот что я сделал, чтобы принять уведомление о разрешении уведомлений на любом языке, нажав вторую кнопку в диалоговом окне (две кнопки). Кнопка "Разрешить" находится справа, поэтому индекс 1.
let handler = addUIInterruptionMonitor(withDescription: "System Dialog") { (alert) -> Bool in
alert.buttons.element(boundBy: 1).tap()
return true
}
app.tap()