web-dev-qa-db-ja.com

addUIInterruptionMonitor(withDescription:handler :)がiOS10または9で機能しない

次のテストはiOS11で正常に機能します。ロケーションサービスを使用する許可を求めるアラートを閉じてから、マップを拡大します。 iOS 10または9では、これは何も行われず、テストは引き続き成功します

func testExample() {
    let app = XCUIApplication()

    var handled = false
    var appeared = false

    let token = addUIInterruptionMonitor(withDescription: "Location") { (alert) -> Bool in
        appeared = true
        let allow = alert.buttons["Allow"]
        if allow.exists {
            allow.tap()
            handled = true
            return true
        }

        return false
    }

    // Interruption won't happen without some kind of action.
    app.tap()

    removeUIInterruptionMonitor(token)
    XCTAssertTrue(appeared && handled)
}

誰かが理由や回避策を知っていますか?

問題を再現できるプロジェクトは次のとおりです。 https://github.com/TitouanVanBelle/Map

更新

Xcode 9.3Betaの変更ログには次のように表示されます

XCTest UI割り込みモニターは、iOS 10を実行しているデバイスとシミュレーターで正しく機能するようになりました。(33278282)

17
_let springboard = XCUIApplication(bundleIdentifier: "com.Apple.springboard") 

let allowBtn = springboard.buttons["Allow"]
if allowBtn.waitForExistence(timeout: 10) {
    allowBtn.tap()
}
_

_.exists_を.waitForExistence(timeout: 10)に更新します。詳細については、コメントを確認してください。

32
River2202

私はこの問題を抱えていました River2202の解決策 私のために働きました。

これはUIInterruptionMonitorを機能させるための修正ではなく、アラートを閉じる別の方法であることに注意してください。 addUIInterruptionMonitorセットアップを削除することもできます。許可アラートが表示される可能性のある場所では、springboard.buttons["Allow"].existsテストを行う必要があります。可能であれば、forceはテストの初期段階で表示されるため、後で再度心配する必要はありません。

幸い、springboard.buttons["Allow"].existsコードはiOS11でも機能するため、単一のコードパスを使用でき、iOS10とiOS11で1つのことを行う必要はありません。

ちなみに、私は基本的な問題(addUIInterruptionMonitorがiOS 11より前では機能しない)をAppleのバグとして記録しました。現在、重複としてクローズされているので、バグだと認識していると思います。

3
Ben

@ River2202ソリューション を使用しましたが、中断よりもうまく機能します。それを使うことにした場合は、ウェイター機能を使うことを強くお勧めします。あらゆる種類のXCUIElementが表示されるのを待つために、これを作成しました。

それを試してみてください!

// function to wait for an ui element to appear on screen, with a default wait time of 20 seconds
// XCTWaiter was introduced after Xcode 8.3, which is handling better the timewait, it's not failing the test.  It uses an enum which returns: 'Waiters can be used with or without a delegate to respond to events such as completion, timeout, or invalid  expectation fulfilment.'
@discardableResult
func uiElementExists(for element: XCUIElement, timeout: TimeInterval = 20) -> Bool {
    let expectation = XCTNSPredicateExpectation(predicate: NSPredicate(format: "exists == true"), object: element)
    let result = XCTWaiter().wait(for: [expectation], timeout: timeout)
    guard result == .completed else {
        return false
    }
    return true
}
1
Cesar Alcaraz