web-dev-qa-db-fra.com

Xcode7 | Tests d'interface utilisateur Xcode | Comment gérer l'alerte de service de localisation?

J'écris des scénarios de test d'interface utilisateur pour l'une de mes applications à l'aide des applications XCUIApplication, XCUIElement et XCUIElementQuery introduites dans Xcode7/iOS 9.

J'ai frappé un barrage routier. L'un des écrans du scénario de test nécessite les services de localisation d'iOS. Comme prévu, l'utilisateur est invité à autoriser l'utilisation du service de localisation avec l'alerte intitulée: Allow “App name” to access your location while you use the app? avec les boutons Allow & Don't Allow

Le problème est ou si, il semble que puisque l'alerte est présentée par le système d'exploitation lui-même, elle n'est pas présente dans le sous-arbre d'éléments d'Application.

Je me suis connecté après:

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

Même l'enregistrement de l'interface utilisateur a généré un code similaire:

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

Je n'ai trouvé aucune API capable de résoudre ce problème. Par exemple:

  • Appuyez sur une position à l'écran
  • Recevez des alertes en dehors de l'application

Alors, comment puis-je surmonter ça? Existe-t-il un moyen de configurer les cibles de test pour que l'autorisation de service de localisation ne soit pas requise.

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

Notez que c'est un peu différent car le nom de la méthode est maintenant addUIInterruptionMonitor et prend withDescription en argument.

Xcode 7.1

Xcode 7.1 a finalement résolu un problème d'alertes système. Il y a cependant deux petites prises.

Tout d'abord, vous devez configurer un "Gestionnaire d'interruption d'interface utilisateur" avant de présenter l'alerte. C’est notre manière de dire au framework comment gérer une alerte quand elle apparaît.

Deuxièmement, après avoir présenté l'alerte, vous devez interagir avec l'interface. Il suffit de taper sur l'application, mais cela est nécessaire.

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

Le "dialogue de localisation" est simplement une chaîne destinée à aider le développeur à identifier le gestionnaire auquel il a accédé. Elle n'est pas spécifique au type d'alerte.

Xcode 7.0

Les éléments suivants ignoreront une seule "alerte système" dans Xcode 7 Beta 6:

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

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

La bêta 6 a introduit une série de correctifs pour les tests d'interface utilisateur et je crois que c'était l'un d'entre eux.

Notez également que j'appelle -element directement sur -alerts. L'appel de -element sur une XCUIElementQuery oblige la structure à choisir le "seul et unique" élément correspondant à l'écran. Cela fonctionne très bien pour les alertes dans lesquelles vous ne pouvez avoir qu'une seule visibilité à la fois. Cependant, si vous essayez ceci pour une étiquette et que vous avez deux étiquettes, la structure générera une exception.

29
Joe Masilotti

C'était la seule chose qui a fonctionné pour moi. Utilisation de Xcode 9 fwiw.

Aussi probablement que je utilisais déjà addUIInterruptionMonitor pour une alerte différente. J'ai essayé de les réorganiser et cela n'a pas fait de différence. Peut-être que c'est un problème lorsque vous en avez deux ou peut-être que je les utilisais mal. En tout état de cause, le code ci-dessous a fonctionné. :)

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

Si vous voulez vérifier si l'alerte est affichée, vérifiez simplement l'existence du bouton:

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

il vérifie si l'alerte est affichée et si elle est affichée, elle la tapera 

3
Joao_dche

Je l’ai fait fonctionner avec ceci sur Xcode 9.4.1 , l’astuce consistait à attendre que le popup apparaisse.

// 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

Sur xcode 9.1, les alertes ne sont traitées que si le périphérique de test dispose d'iOS 11. Ne fonctionne pas sur les anciennes versions iOS, par exemple 10.3, etc. Référence: https://forums.developer.Apple.com/thread/86989

Pour gérer les alertes, utilisez ceci:

//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

Cela fonctionne pour toutes les langues:

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

Pour taper sur autoriser l'alerte de lieu, vous pouvez appeler Element.tap () où élément est un élément de votre écran. Ainsi, après avoir appelé, appuyez sur Access, appuyez sur Autoriser en alerte, puis appuyez sur votre élément.

0
Andrey