在iOS应用程序的UI测试中禁用等待空闲状态
问题基本上与此相同: 我在视图中不断重复使用“背景动画”。这个!@$$$&@Xcode/iOS的UI测试需要等待所有UIView动画结束,然后才考虑应用程序空闲,并继续进行点击按钮等操作。这与我们设计应用程序的方式不符。(特别是,我们有一个按钮,它使用在iOS应用程序的UI测试中禁用等待空闲状态,ios,xcode-ui-testing,Ios,Xcode Ui Testing,问题基本上与此相同: 我在视图中不断重复使用“背景动画”。这个!@$$$&@Xcode/iOS的UI测试需要等待所有UIView动画结束,然后才考虑应用程序空闲,并继续进行点击按钮等操作。这与我们设计应用程序的方式不符。(特别是,我们有一个按钮,它使用UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse选项设置动画,因此它永远不会停止。) 但我认为可能有某种方法可以关闭和/或缩短“等待应用程序空闲”状态。有?怎么用?有其他办
UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
选项设置动画,因此它永远不会停止。)
但我认为可能有某种方法可以关闭和/或缩短“等待应用程序空闲”状态。有?怎么用?有其他办法吗?不幸的是,使用苹果的UI测试,你不能打开“等待应用程序空闲”或轮询其他网络活动,但是你可以使用环境变量禁用应用程序中的动画,以使测试更稳定。在测试之前的设置方法中,设置如下环境变量
override func setUp() {
super.setUp()
continueAfterFailure = false
let app = XCUIApplication()
app.launchEnvironment = ["UITEST_DISABLE_ANIMATIONS" : "YES"]
app.launch()
}
现在在源代码中:
if (ProcessInfo.processInfo.environment["UITEST_DISABLE_ANIMATIONS"] == "YES") {
UIView.setAnimationsEnabled(false)
}
如果您只想在特定视图中禁用该特定视图的动画,或者在代理文件中禁用整个应用程序的动画,则可以将该复选框放置在特定视图中。您实际上可以禁用
等待应用程序空闲。这是一次黑客攻击,可能不稳定。禁用动画,并且启用此黑客攻击,我看到大约20%的性能提升(在禁用动画的性能提升之上)
你所要做的就是关闭调用的方法,使应用程序空闲,而不运行它。该方法是xguiapplicationprocesswaitforquiesceincludinganizationsidle:
这是我在swift 3中的工作解决方案-可能有更好的方法,但这对概念验证有效
扩展XCTestCase
类。我将调用我的MyTestCase
static var swizzledOutIdle = false
override func setUp() {
if !MyTestCase.swizzledOutIdle { // ensure the swizzle only happens once
let original = class_getInstanceMethod(objc_getClass("XCUIApplicationProcess") as! AnyClass, Selector(("waitForQuiescenceIncludingAnimationsIdle:")))
let replaced = class_getInstanceMethod(type(of: self), #selector(MyTestCase.replace))
method_exchangeImplementations(original, replaced)
MyTestCase.swizzledOutIdle = true
}
super.setUp()
}
@objc func replace() {
return
}
注意等待应用程序空闲
将不再出现在日志中 我在Objective-C中使用了GH123人答案,以防有人需要:
- (void)disableWaitForIdle {
SEL originalSelector = NSSelectorFromString(@"waitForQuiescenceIncludingAnimationsIdle:");
SEL swizzledSelector = @selector(doNothing);
Method originalMethod = class_getInstanceMethod(objc_getClass("XCUIApplicationProcess"), originalSelector);
Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
- (void)doNothing {
// no-op
}
我在Objective-C中使用了h.w.powers的解决方案,以防有人需要
设置:
XCUIApplication *app = [[XCUIApplication alloc] init];
app.launchEnvironment = @{@"UITEST_DISABLE_ANIMATIONS":@"YES"};
[app launch];
然后在你的代码里
if ([[[NSProcessInfo processInfo] environment][@"UITEST_DISABLE_ANIMATIONS"] isEqualToString:@"YES"]) {
// do something like stopping the animation
}
我在几个测试类的setUp()中使用了gh123man的解决方案,在升级到ios13.3之前,它一直很有魅力。从那时起,应用程序就陷入了启动状态
发现如果我将其移动到disableWaitForIdle()和enableWaitForIdle()等方法,并仅以最精细的方式调用它们(在点击之前和之后,我知道应用程序将永远不会变为空闲),它仍然有效,例如:
@discardableResult func selectOption() -> Self {
disableWaitForIdle()
app.cells["Option"].firstMatch.waitAndForceTap(timeout: 20)
enableWaitForIdle()
return self
}
谢谢,这就是我现在要做的。这并不完美,但可能是目前唯一的办法。可以告诉动画只运行一次迭代等。只是为了澄清,应该是让app=xguiapplication()app.launchenEnvironment=[“UITEST\u DISABLE\u Animations:“YES”]app.launch()
我一直在试图弄清楚发生了什么,这就是问题所在,谢谢!!工作起来很有魅力!此外,您可以提到,由于这一点,在某些情况下,有必要使用waitForExistence
功能–因为速度;)哦,天哪,这太棒了。80年代的测试都是“等待应用程序空闲”的废话,现在它做了我希望它做的事情,在iOS 13.1和XCode 11.1的iPad上运行良好,谢谢。@gh123man有没有办法对Android做同样的事情?这并没有提供问题的答案。您可以,也可以参考页面右侧的相关和链接问题来找到答案。如果您有一个相关但不同的问题,并包含指向此问题的链接以帮助提供上下文。请参阅:感谢您对U10转发的评论。我找到了一个方法使它工作,并更新了我的答案。