Xcode 7 UItesting:closures推送和位置警报

我遇到了Xcode 7 UItesting的问题。

该应用程序在用户login后显示两个警报, 请求位置警报和推送通知警报。 这些通知一个接一个地显示出来。 位置第一个出现。

我试图自动解雇他们开始我的testing。

为了做到这一点,我添加了两个UIInterruptionMonitor ,第一个是位置警报,第二个是通知推送警报。

addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in /* Dismiss Location Dialog */ if alert.collectionViews.buttons["Allow"].exists { alert.collectionViews.buttons["Allow"].tap() return true } return false } addUIInterruptionMonitorWithDescription("Push Dialog") { (alert) -> Bool in /* Dismiss Push Dialog */ if alert.collectionViews.buttons["OK"].exists { alert.collectionViews.buttons["OK"].tap() return true } return false } 

但是只有位置被触发,推送通知UIInterruptionMonitor的处理程序永远不会被调用。

如果在请求位置 UIInterruptionMonitor中返回true,则此另一个post接受的答案指定。 这两个处理程序都被调用,但UIInterruptionMonitor中警报参数链接到请求位置警报视图,因此从未find“确定”button。

我怎样才能解雇这两个连续的警报视图?

虽然不理想,但我发现,如果您只需等到一个授权对话框完成,然后再在应用程序中显示另一个授权对话框,UItesting就可以连续获取多个请求。

  if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse || CLLocationManager.authorizationStatus() == .AuthorizedAlways { self.locationManager.requestLocation() } else { self.contactStore.requestAccessForEntityType(.Contacts) { _ in self.locationManager.requestWhenInUseAuthorization() } } 

我实际上是要求访问我的代码中不同位置的联系人,但是它可以处理多个同时发生的请求。

然后在我的testing中:

  addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in let button = alert.buttons["Allow"] if button.exists { button.tap() return true } return false } addUIInterruptionMonitorWithDescription("Contacts Dialog") { (alert) -> Bool in let button = alert.buttons["OK"] if button.exists { button.tap() return true } return false } app.buttons["Location"].tap() app.tap() // need to interact with the app for the handler to fire app.tap() // need to interact with the app for the handler to fire 

正如我在您提到的答案中指出的那样, 在出现警报之后,您必须与应用程序进行交互。

其次,在显示警报之后,您必须与界面进行交互。 简单地点击应用程序工作得很好,但是是必需的。

 // add UI interruption handlers app.buttons["Request Location"].tap() app.tap() // need to interact with the app for the handler to fire 
 class BaseTest: XCTestCase { let pushSent = NSNotification.Name.init("alert.pushSent") var notificationMonitor: NSObjectProtocol? override func setUp() { listenNotifications() let app = XCUIApplication() notificationMonitor = addUIInterruptionMonitor(withDescription: "Push Notifications") { [unowned self] (alert) -> Bool in let btnAllow = app.buttons["Allow"] //1: if btnAllow.exists { btnAllow.tap() NotificationCenter.default.post(name: self.pushSent, object: nil) return true } //2: //takeScreenshot XCTFail("Unexpected System Alert") return false } //3: //add code for "Request Location" monitor app.launchEnvironment = ["UITEST_DISABLE_ANIMATIONS" : "YES"] //4: app.launch() } func listenNotifications() { NotificationCenter.default.addObserver(forName: pushSent, object: nil, queue: nil) { (notification) in if let locationDialogHandeler = self.notificationMonitor { //5: self.removeUIInterruptionMonitor(locationDialogHandeler) } } } } 

1:检查你是否在正确的警报,点击button,并find一种方法来删除显示器(我使用NotificationCenter)

2:如果你进入监视器,找不到正确的button,这意味着这是一个意外的stream程。 testing失败(但是先截图)。

3:添加其他显示器

4:我甚至在启动应用程序之前添加显示器。 如果在出现警报后添加监视器,则不会触发警报。

5:移除监视器,当出现新警报时,堆栈中的下一个监视器将被调用。

PS:您应该以相反的顺序添加监视器,因此,在“推送通知”之后添加“请求位置”

要closures系统警报视图(即: 推送通知 ),您可以为testing环境定义自定义标志 。

然后,你只需要改变应用程序的代码,以避免特定的初始化(即推送通知 ):

 #if !TESTING let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil) application.registerUserNotificationSettings(settings) #endif 

我使用这个技巧,以便能够快照截图。