Xcode 7用户界面testing:如何解除代码中的一系列系统警报
我正在编写使用新的Xcode 7 UItestingfunction的UItesting用例。 在我的应用程序的某个时候,我要求用户许可摄像头访问和推送通知。 因此,两个iOSpopup窗口将显示: "MyApp Would Like to Access the Camera"
popup窗口和"MyApp Would Like to Send You Notifications"
popup。 我想我的testing,以消除这两个popup窗口。
UIlogging为我生成了以下代码:
[app.alerts[@"cameraAccessTitle"].collectionViews.buttons[@"OK"] tap];
但是, [app.alerts[@"cameraAccessTitle"] exists]
parsing为false,上面的代码生成一个错误: Assertion Failure: UI Testing Failure - Failure getting refresh snapshot Error Domain=XCTestManagerErrorDomain Code=13 "Error copying attributes -25202"
。
那么在testing中解除一堆系统警报的最好方法是什么? 系统popup窗口中断我的应用程序stream程,并立即失败我的正常UItesting用例。 事实上,有关如何绕过系统警报的任何build议,所以我可以恢复testing通常的stream程,赞赏。
这个问题可能与这个SOpost有关,也没有答案: Xcode7 | Xcode UItesting| 如何处理位置服务警报?
提前致谢。
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
“位置对话框”只是一个string,用于帮助开发人员识别哪个处理程序被访问过,而不是特定于警报的types。
我相信从处理程序返回true
表示它是“完整的”,这意味着它不会再被调用。 对于你的情况,我会尝试返回false
所以第二个警报将再次触发处理程序。
Xcode 7.0
以下将closuresXcode 7 Beta 6中的一个“系统警报”:
let app = XCUIApplication() app.launch() // trigger location permission dialog app.alerts.element.collectionViews.buttons["Allow"].tap()
Beta 6为UItesting引入了一系列修复,我相信这是其中之一。
还要注意,我直接在-alerts
上调用-alerts
。 在XCUIElementQuery
上调用XCUIElementQuery
强制框架在屏幕上select“唯一”的匹配元素。 这对于一次只能有一个可见的警报很有用。 但是,如果您尝试使用这个标签并且有两个标签,框架将会引发exception。
天哪。 它总是点击“不允许”,即使我故意说点击“允许”
至less
` if app.alerts.element.collectionViews.buttons["Allow"].exists { app.tap() }`
允许我继续前进,并做其他testing。
神! 我讨厌XCTest最糟糕的时间处理UIView警报。 我有一个应用程序,我得到2警报第一个要我select“允许”启用位置服务的应用程序的权限,然后在启动页面用户不得不按下UIButton称为“打开位置”,最后有一个在UIViewAlert中通知短信提醒,用户必须select“确定”。 我们遇到的问题是无法与系统警报进行交互,但也是一种竞争状态,在屏幕上的行为和外观是不合时宜的。 看来如果你使用alert.element.buttons["whateverText"].tap
XCTest的逻辑就是保持按下直到testing时间结束。 所以基本上一直按住屏幕上的任何东西,直到所有的系统警报都清晰可见。
这是一个黑客,但这是为我工作。
func testGetPastTheStupidAlerts(){ let app = XCUIApplication() app.launch() if app.alerts.element.collectionViews.buttons["Allow"].exists { app.tap() } app.buttons["TURN ON MY LOCATION"].tap() }
string“允许”被完全忽略, app.tap()
的逻辑被称为evreytime,一个警报在视图中,最后我想要达到的button[“打开位置”]可以访问,testing通过
〜完全困惑,谢谢苹果。
目标 – C
-(void) registerHandlerforDescription: (NSString*) description { [self addUIInterruptionMonitorWithDescription:description handler:^BOOL(XCUIElement * _Nonnull interruptingElement) { XCUIElement *element = interruptingElement; XCUIElement *allow = element.buttons[@"Allow"]; XCUIElement *ok = element.buttons[@"OK"]; if ([ok exists]) { [ok tap]; return YES; } if ([allow exists]) { [allow tap]; return YES; } return NO; }]; } -(void)setUp { [super setUp]; self.continueAfterFailure = NO; self.app = [[XCUIApplication alloc] init]; [self.app launch]; [self registerHandlerforDescription:@"“MyApp” would like to make data available to nearby Bluetooth devices even when you're not using app."]; [self registerHandlerforDescription:@"“MyApp” Would Like to Access Your Photos"]; [self registerHandlerforDescription:@"“MyApp” Would Like to Access the Camera"]; }
迅速
addUIInterruptionMonitorWithDescription("Description") { (alert) -> Bool in alert.buttons["Allow"].tap() alert.buttons["OK"].tap() return true }
我发现的唯一可靠的解决方法是设置两个单独的testing来处理警报。 在第一个testing中,我打电话给app.tap()
,不做别的。 在第二个testing中,我再次调用app.tap()
,然后做真正的工作。
听起来就像实现摄像头访问的方法,通知按照您的说法进行线程化处理,但没有进行物理上的pipe理,只是在显示时显示方式。
我怀疑其中一个是由另一个触发的,当它以编程方式点击时,它也会擦除另一个(Apple可能永远不会允许)
想想看,你要求用户许可,然后代表他们作出决定? 为什么? 因为你可能无法让你的代码工作。
如何解决 – 跟踪这两个组件触发popup对话框的位置 – 被调用的位置?重写为只触发一个,当一个对话框完成时发送NSNotification触发并显示剩余的对话框。
我会严重阻碍编程方式为用户点击对话button的方法。