addUIInterruptionMonitor(withDescription:handler :)无法在iOS 10或9上运行

时间:2017-07-21 03:08:48

标签: ios swift xctest xcode-ui-testing

以下测试在iOS 11上运行正常。它解除了警告,要求使用位置服务的权限,然后放大地图。在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.3 Beta的更新日志显示以下内容

XCTest UI interruption monitors now work correctly on devices and simulators running iOS 10. (33278282)

3 个答案:

答案 0 :(得分:23)

    let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") 

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

.exists更新为.waitForExistence(timeout: 10),详情请查看评论。

答案 1 :(得分:3)

我遇到了这个问题,River2202's solution为我工作。

请注意,这不是让UIInterruptionMonitor工作的解决方法,而是一种解除警报的不同方法。您也可以删除addUIInterruptionMonitor设置。您需要在可能出现权限警报的任何地方进行springboard.buttons["Allow"].exists测试。如果可能的话,强制它会在测试的早期阶段出现,所以您以后不必再担心它。

令人高兴的是,springboard.buttons["Allow"].exists代码仍可在iOS 11中运行,因此您可以使用单个代码路径,而不必为iOS 10执行一项操作,而为iOS 11执行另一项操作。

顺便说一句,我记录了基本问题(addUIInterruptionMonitor在iOS 11之前不工作)作为Apple的错误。它现在已经关闭了,所以我猜他们承认这是一个错误。

答案 2 :(得分:1)

我使用了@River2202 solution,它的效果比打断的效果更好。 如果您决定使用它,我强烈建议您使用侍者功能。我创建这个是为了等待任何一种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
}