Xcode7 | Xcode UI测试|如何处理位置服务警报?

时间:2015-07-31 12:28:14

标签: xcode xctest ios9 xcode7-beta4 xcode-ui-testing

我正在使用Xcode7 / iOS 9中引入的XCUIApplication,XCUIElement和XCUIElementQuery为我的应用程序编写UI测试用例。

我遇到了路障。测试用例中的一个屏幕需要iOS的位置服务。正如预期的那样,系统会提示用户允许使用位置服务,其标题为:Allow “App name” to access your location while you use the app? Allow& Don't Allow个按钮。

问题似乎是左右,因为警报由操作系统本身呈现,因此它不存在于应用程序的元素子树中。

我记录了以下内容:

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

即使是UI录制也生成了类似的代码:

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

我没有找到任何可以让我解决这个问题的API。例如:

  • 点击屏幕上的某个位置
  • 在应用外部获取提醒

那么我怎么能超越这个呢?有没有办法配置测试目标,以便不需要位置服务授权。

8 个答案:

答案 0 :(得分:29)

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

请注意,它有点不同,因为方法名称现在是addUIInterruptionMonitor并将withDescription作为参数

Xcode 7.1

Xcode 7.1最终修复了系统警报的问题。然而,有两个小问题。

首先,您需要在显示警报之前设置“UI Interuption Handler”。这是告诉框架如何处理警报的方式。

其次,在显示警报后,您必须与界面进行交互。只需点击应用程序就可以了,但是是必需的。

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

“位置对话框”只是一个字符串,可以帮助开发人员识别访问哪个处理程序,而不是特定于警报类型。

Xcode 7.0

以下内容将消除Xcode 7 Beta 6中的单个“系统警报”:

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

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

Beta 6为UI测试引入了一系列修复程序,我相信这是其中之一。

另请注意,我直接在-element上致电-alerts。在-element上调用XCUIElementQuery会强制框架在屏幕上选择“唯一的”匹配元素。这适用于一次只能显示一个警报的警报。但是,如果您为标签尝试此操作并且有两个标签,则框架将引发异常。

答案 1 :(得分:7)

这是唯一对我有用的东西。使用Xcode 9 fwiw。

也可能与我已经使用addUIInterruptionMonitor用于其他警报相关。我尝试重新排序它们并没有什么区别。当你有两个时,可能是9中的问题,或者可能是我错误地使用它们。无论如何,下面的代码都有效。 :)

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

答案 2 :(得分:3)

如果要检查警报是否显示,只需检查是否存在按钮:

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

检查警报是否正在显示,如果显示警报则会点击

答案 3 :(得分:3)

我可以在 Xcode 9.4.1 上使用它,诀窍是等待弹出窗口出现。

// 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()
    }

答案 4 :(得分:2)

在xcode 9.1上,仅在测试设备具有iOS 11 时才会处理警报。不适用于较旧的iOS版本,例如10.3等。参考:https://forums.developer.apple.com/thread/86989

要处理警报,请使用:

x = parseInt(x);
y = parseInt(y);

var z1 = 0;
var z2 = 0;

...

z1=x+1:
z2=y;

...

array[z1][z2] = 10;

答案 5 :(得分:1)

这适用于所有语言:

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

答案 6 :(得分:0)

要点按允许位置提醒,您可以拨打电话 element.tap()其中element是屏幕上的任何元素。 因此,在调用tap后,辅助功能将点击“在提醒状态下允许”而不是点按您的元素

答案 7 :(得分:0)

这是我通过点击(两个按钮)对话框中找到的第二个按钮来接受任何语言的通知权限警报的方法。 “允许”按钮在右侧,因此索引为1。

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