webentwicklung-frage-antwort-db.com.de

Xcode7 | Xcode-UI-Tests | Umgang mit Standortdienstalarm

Ich schreibe UI-Testfälle für eine meiner Apps mit XCUIApplication, XCUIElement und XCUIElementQuery, die in Xcode7/iOS 9 eingeführt wurden.

Ich habe eine Straßensperre getroffen. Für einen der Bildschirme im Testfall sind die Location Services von iOS erforderlich. Wie erwartet wird der Benutzer aufgefordert, die Verwendung des Ortungsdienstes mit der Warnung mit dem Titel Allow “App name” to access your location while you use the app? mit den Tasten Allow & Don't Allow zuzulassen. 

Problem ist oder so scheint es, dass der Alarm, da er vom Betriebssystem selbst angezeigt wird, nicht in der Element-Baumstruktur von Application vorhanden ist.

Ich habe folgendes angemeldet:

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

Selbst die Aufzeichnung der Benutzeroberfläche erzeugte einen ähnlichen Code:

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

Ich habe keine API gefunden, durch die ich an diesem Problem vorbeikommen kann. Zum Beispiel:

  • Tippen Sie auf eine Position auf dem Bildschirm
  • Erhalten Sie Benachrichtigungen außerhalb der App

Wie kann ich das überwinden? Gibt es eine Möglichkeit, Testziele so zu konfigurieren, dass die Standortdienstautorisierung nicht erforderlich ist.

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

Beachten Sie, dass es ein bisschen anders ist, da der Methodenname jetzt addUIInterruptionMonitor lautet und withDescription als Argument verwendet

Xcode 7.1

Xcode 7.1 hat endlich ein Problem mit Systemwarnungen behoben. Es gibt jedoch zwei kleine Fallstricke.

Zunächst müssen Sie einen "UI-Interruption-Handler" einrichten, bevor Sie die Warnung ausgeben. Auf diese Weise teilen wir dem Framework mit, wie eine Warnung behandelt werden soll, wenn sie erscheint.

Zweitens müssen Sie nach der Anzeige der Warnung mit der Schnittstelle interagieren. Ein einfaches Tippen auf die App funktioniert einwandfrei, ist jedoch erforderlich.

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

Der "Positionsdialog" ist nur eine Zeichenfolge, mit der der Entwickler feststellen kann, auf welchen Handler zugegriffen wurde. Er ist nicht spezifisch für den Alarmtyp.

Xcode 7.0

Im Folgenden wird ein einzelner "Systemalarm" in Xcode 7 Beta 6 verworfen:

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

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

Beta 6 hat eine Reihe von Korrekturen für UI-Tests eingeführt, und ich glaube, dass dies einer von ihnen war.

Beachten Sie auch, dass ich -element direkt über -alerts anrufe. Der Aufruf von -element für eine XCUIElementQuery zwingt das Framework, das übereinstimmende "einzige" Element auf dem Bildschirm auszuwählen. Dies funktioniert hervorragend für Warnungen, bei denen jeweils nur eine angezeigt werden kann. Wenn Sie dies jedoch für ein Label versuchen und zwei Labels haben, löst das Framework eine Ausnahme aus.

29
Joe Masilotti

Dies war das einzige, was für mich funktionierte. Verwendung von Xcode 9 fwiw.

Möglicherweise auch relevant, dass ich addUIInterruptionMonitor bereits für eine andere Warnung verwendet habe. Ich habe versucht, sie neu zu ordnen, und es machte keinen Unterschied. Könnte sein, dass es in 9 ein Problem ist, wenn Sie zwei haben, oder dass ich sie falsch verwendet habe. In jedem Fall funktionierte der folgende Code. :)

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

Wenn Sie prüfen möchten, ob die Warnung angezeigt wird, prüfen Sie einfach, ob die Schaltfläche vorhanden ist:

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

es wird geprüft, ob die Warnung angezeigt wird, und wenn es angezeigt wird, tippt es darauf 

3
Joao_dche

Ich bekam es mit Xcode 9.4.1 damit zu arbeiten, der Trick bestand darin zu warten, bis das Popup erscheint.

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

Auf xcode 9.1 werden Warnmeldungen nur verarbeitet, wenn das Testgerät über iOS 11 verfügt. Funktioniert nicht mit älteren iOS-Versionen, z. B. 10.3 usw. Referenz: https://forums.developer.Apple.com/thread/86989

Um mit Alerts umzugehen, verwenden Sie folgendes:

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

Dies funktioniert für alle Sprachen:

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

Hier ist, was ich getan habe, um einen Benachrichtigungs-Berechtigungsalarm in einer beliebigen Sprache zu akzeptieren, indem ich auf die zweite Schaltfläche im Dialogfeld (zwei Schaltflächen) tippe. Die Schaltfläche Zulassen befindet sich rechts, daher Index 1.

let handler = addUIInterruptionMonitor(withDescription: "System Dialog") { (alert) -> Bool in
    alert.buttons.element(boundBy: 1).tap()
    return true
}
app.tap()
0

Zum Tippen auf "Vor Ort zulassen" können Sie Element.tap () aufrufen, wobei element ein Element auf Ihrem Bildschirm ist. Nach dem Aufrufen von tippen Sie auf Erlaubnis und dann auf Ihr Element

0
Andrey