Xcode 7 UI 测试:关闭推送和位置警报
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33875301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Xcode 7 UI Testing: Dismiss Push and Location alerts
提问by Thomas LEVY
I encountered a problem with Xcode 7 UI Testing.
我在 Xcode 7 UI 测试中遇到了问题。
The app displays two alerts after my user logs in, the Request LocationAlert and the Push NotificationsAlert. Those notifications are shown one right after the other. The Location one appears first.
该应用程序在我的用户登录后显示两个警报,请求位置警报和推送通知警报。这些通知一个接一个地显示。位置一首先出现。
I try to dismiss them automatically to start my tests.
我尝试自动关闭它们以开始我的测试。
In order to do that, I add two UIInterruptionMonitor, the first one for the Location Alert and the second one for the Notification Push Alert.
为了做到这一点,我添加了两个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
}
But only the Location one is triggered, the handler of Push Notifications UIInterruptionMonitoris never called.
但只有位置一被触发,推送通知UIInterruptionMonitor的处理程序永远不会被调用。
If I return true in the Request LocationUIInterruptionMonitoras this other post accepted answerspecifies. Both handler are called but the alertparameter in both UIInterruptionMonitorlinks to the Request LocationAlert View so the "OK" button is never found.
如果我在请求位置UIInterruptionMonitor 中返回 true作为这个其他帖子接受的答案指定。两个处理程序都被调用,但UIInterruptionMonitor 中的警报参数链接到请求位置警报视图,因此永远找不到“确定”按钮。
How can I dismiss those two successive alerts views?
如何关闭这两个连续的警报视图?
回答by David Beck
While not ideal, I found that if you simply wait until one authorization dialog has finished before presenting another one in the app, UI tests can pick up multiple requests in a row.
虽然并不理想,但我发现如果您只是等到一个授权对话框完成后再在应用程序中呈现另一个,UI 测试可以连续获取多个请求。
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse || CLLocationManager.authorizationStatus() == .AuthorizedAlways {
self.locationManager.requestLocation()
} else {
self.contactStore.requestAccessForEntityType(.Contacts) { _ in
self.locationManager.requestWhenInUseAuthorization()
}
}
I'm actually requesting access to contacts in a different place in my code, but it can handle multiple simultaneous requests just fine.
我实际上是在我的代码中请求访问不同位置的联系人,但它可以很好地处理多个同时请求。
Then in my test:
然后在我的测试中:
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
回答by Joe Masilotti
As I noted in the answer you mentioned, you must interact with the application after the alert appears.
正如我在您提到的答案中指出的那样,您必须在警报出现后与应用程序进行交互。
Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.
其次,在呈现警报后,您必须与界面进行交互。只需点击应用程序就可以正常工作,但这是必需的。
// add UI interruption handlers
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
回答by Daniel Carlos
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: Check if you're in the correct alert, tap the button and find a way to remove the monitor (I'm using NotificationCenter)
1:检查您是否处于正确的警报中,点击按钮并找到移除监视器的方法(我正在使用通知中心)
2: If you enter a monitor and can not find the right button, it means it's an unexpected flow. Fail the test (but take a screenshot first).
2:如果你进入一个监视器,找不到正确的按钮,则表示这是一个意外的流程。测试失败(但先截图)。
3: Add other monitors
3:添加其他显示器
4: I am adding monitor even before launching the app. If you add a monitor after the alert appears, it will not be triggered.
4:我什至在启动应用程序之前添加监视器。如果在警报出现后添加监视器,则不会触发。
5: Remove the monitor, that way when a new alert appears, the next monitor in the stack will be called.
5:移除监视器,这样当出现新警报时,堆栈中的下一个监视器将被调用。
P.S: You should add monitors in reverse order, therefore, add "Request Location" after "Push Notifications"
PS:您应该以相反的顺序添加监视器,因此,在“推送通知”之后添加“请求位置”
回答by KuiKui
To dismiss system alert views (ie: Push Notification) you can define custom flags for the testing environment.
要关闭系统警报视图(即:推送通知),您可以为测试环境定义自定义标志。
Then, you just have to change the application's code to avoid specific initialisations (ie: Push Notification) :
然后,您只需更改应用程序的代码以避免特定的初始化(即:推送通知):
#if !TESTING
let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
#endif
I use this trick in order to be able to take screenshots with snapshot.
我使用这个技巧是为了能够使用snapshot截取屏幕截图。