Xcode 7のUIテストで問題が発生しました。
ユーザーがログインした後、アプリに2つのアラートが表示されます。Request LocationAlertとPush Notificationsアラート。これらの通知は、次々に表示されます。場所1が最初に表示されます。
私はテストを開始するためにそれらを自動的に却下しようとします。
そのために、2つUIInterruptionMonitorを追加します。1つ目はロケーションアラート用で、2つ目は通知プッシュアラート用です。
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
}
ただし、ロケーション1のみがトリガーされ、プッシュ通知UIInterruptionMonitorのハンドラーが呼び出されることはありません。
Request LocationUIInterruptionMonitorでtrueを返す場合 この他の投稿は回答を受け入れました を指定します。両方のハンドラーが呼び出されますが、両方のUIInterruptionMonitorのalertパラメーターがRequest Location[OK]ボタンが見つからないようにアラートビュー。
これら2つの連続するアラートビューを閉じるにはどうすればよいですか?
理想的ではありませんが、1つの承認ダイアログが終了するまで待ってから、アプリで別の承認ダイアログを表示すると、UIテストで複数のリクエストを連続して取得できることがわかりました。
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse || CLLocationManager.authorizationStatus() == .AuthorizedAlways {
self.locationManager.requestLocation()
} else {
self.contactStore.requestAccessForEntityType(.Contacts) { _ in
self.locationManager.requestWhenInUseAuthorization()
}
}
実際にはコードの別の場所にある連絡先へのアクセスを要求していますが、複数の同時要求を問題なく処理できます。
その後、私のテストでは:
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:正しいアラートにいるかどうかを確認し、ボタンをタップして、モニターを削除する方法を見つけます(NotificationCenterを使用しています)
2:モニターに入っても正しいボタンが見つからない場合、それは予期しないフローであることを意味します。テストに失敗します(ただし、最初にスクリーンショットを撮ります)。
3:他のモニターを追加する
4:アプリを起動する前でもモニターを追加しています。アラートが表示された後にモニターを追加しても、トリガーされません。
5:モニターを削除すると、新しいアラートが表示されたときに、スタック内の次のモニターが呼び出されます。
PS:モニターは逆の順序で追加する必要があるため、「プッシュ通知」の後に「リクエストの場所」を追加します。