Xcode7 | Pruebas Xcode UI | ¿Cómo manejar la alerta de servicio de ubicación?
xctest ios9 (7)
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
Tenga en cuenta que es un poco diferente, ya que el nombre del método ahora es addUIInterruptionMonitor y toma withDescription como argumento
Xcode 7.1
Xcode 7.1 finalmente ha solucionado un problema con las alertas del sistema. Hay, sin embargo, dos pequeños errores.
Primero, debe configurar un "Controlador de Interrupción de UI" antes de presentar la alerta. Esta es nuestra manera de decirle al marco cómo manejar una alerta cuando aparece.
Segundo, luego de presentar la alerta debes interactuar con la interfaz. Simplemente tocando la aplicación funciona bien, pero es necesario.
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
El "Cuadro de diálogo de ubicación" es solo una cadena para ayudar al desarrollador a identificar a qué controlador se accedió, no es específico del tipo de alerta.
Xcode 7.0
Lo siguiente descartará una sola "alerta del sistema" en Xcode 7 Beta 6:
let app = XCUIApplication()
app.launch()
// trigger location permission dialog
app.alerts.element.collectionViews.buttons["Allow"].tap()
Beta 6 introdujo una serie de correcciones para las pruebas de UI y creo que esta fue una de ellas.
También tenga en cuenta que estoy llamando a -element
directamente en las -alerts
. Al llamar a -element
en una XCUIElementQuery
, el marco debe elegir el elemento "único y único" en la pantalla. Esto funciona muy bien para alertas donde solo puede tener una visible a la vez. Sin embargo, si intenta esto para una etiqueta y tiene dos etiquetas, el marco generará una excepción.
Estoy escribiendo Casos de prueba de UI para una de mis aplicaciones utilizando XCUIApplication, XCUIElement y XCUIElementQuery introducidas en Xcode7 / iOS 9.
He golpeado un bloqueo de carretera. Una de las pantallas en caso de prueba requiere los Servicios de Localización de iOS. Como era de esperar, se le solicita al usuario que permita el uso del servicio de ubicación con una alerta titulada: ¿ Allow “App name” to access your location while you use the app?
con los botones Allow
y Don''t Allow
.
Parece que el problema es que, dado que la alerta es presentada por el propio sistema operativo, no está presente en el subárbol de elementos de la aplicación.
He registrado los siguientes
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
Incluso la grabación de UI generó un código similar:
XCUIApplication().alerts["Allow “App Name” to access your location while you use the app?"].collectionViews.buttons["Allow"].tap()
No he encontrado ninguna API que me permita superar este problema. Por ejemplo:
- Toque en una posición en la pantalla
- Recibe alertas fuera de la aplicación
Entonces, ¿cómo puedo pasar esto? ¿Hay alguna forma de configurar los objetivos de prueba para que no se requiera la autorización del servicio de ubicación?
Conseguí que funcionara con esto en Xcode 9.4.1 , el truco era esperar a que aparezca la ventana emergente.
// 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()
}
Esto fue lo único que funcionó para mí. Utilizando Xcode 9 fwiw.
También es probable que addUIInterruptionMonitor
en addUIInterruptionMonitor
ya estaba usando addUIInterruptionMonitor
para una alerta diferente. Intenté reordenarlos y no hizo una diferencia. Podría ser que es un problema en 9 cuando tienes dos, o podría ser que los estaba usando mal. En cualquier caso, el siguiente código funcionó. :)
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons["Allow"]
if allowBtn.exists {
allowBtn.tap()
}
Esto funciona para todos los idiomas:
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons.element(boundBy: 2)
if allowBtn.exists {
allowBtn.tap()
}
Para tocar en alerta de ubicación, puede llamar a element.tap () donde elemento es cualquier elemento en su pantalla. Entonces, después de llamar a tap, la accesibilidad tocará Permitir alerta y luego tocará tu elemento
Si desea verificar si la alerta se está mostrando, solo verifique la existencia del botón:
if (app.alerts.element.collectionViews.buttons["Dismiss"].exists)
{
app.alerts.element.collectionViews.buttons["Dismiss"].tap()
}
comprueba si la alerta se muestra y si la muestra la tocará
En xcode 9.1, las alertas solo se manejan si el dispositivo de prueba tiene iOS 11 . No funciona en versiones anteriores de iOS, por ejemplo, 10.3, etc. Referencia: https://forums.developer.apple.com/thread/86989
Para manejar alertas usa esto:
//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