[英]How to clear NSUserDefaults programmatically in XCUITest using Simulator
我已经阅读了几个与此相关的答案,他们建议执行以下操作之一,但这些选项对我不起作用。 我有一个XCUITest,我试图在运行其余的XCUITest之前清除标准用户默认值。 目前我的测试应用程序有一个调用此代码的按钮。 我也尝试直接从XCUITest中调用此代码(我不确定这是否可以使用或者是否需要在应用程序内运行)。
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
我也试过逐个删除:
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"MyKey1"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"MyKey2"];
我还尝试了上面的每个方法,然后是同步调用:
[[NSUserDefaults standardUserDefaults] synchronize];
下次我从NSUserDefaults读取@“MyKey1”时,它仍然具有旧值并且尚未被删除。
在模拟器中运行XCUITest时,有没有办法以编程方式从NSUserDefaults中删除对象? 这些都是自动化测试,所以我不能总是手动点击xcode中的“重置内容和设置”。
谢谢!
通过在测试运行应用程序之前设置UserDefaults值(而不是之后),有几种方法可以解决您的问题。
使用某些键模拟UserDefaults值launchArguments
:
func testExample() {
let app = XCUIApplication()
app.launchArguments += ["-keepScreenOnKey", "YES"]
app.launch()
}
请注意 keepScreenOnKey
键之前的keepScreenOnKey
。 减号表示它应该将下一个启动参数值作为该UserDefaults键的值。
如果您使用的是SwiftyUserDefaults库,则以前的解决方案可能无效。 在这种情况下,有一个优雅的解决方案:如果应用程序在UI测试下运行,则从应用程序中清除所有UserDefaults数据。 应用程序如何知道它是否在UI测试下运行? 通过传递启动参数消息,如下所示:
override func setUp() {
super.setUp()
app.launchArguments += ["UI-Testing"]
}
然后,在AppDelegate.swift
检查应用程序是否在UI-Testing
下运行并删除所有UserDefaults数据(就像您一样):
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
setStateForUITesting()
return true
}
static var isUITestingEnabled: Bool {
get {
return ProcessInfo.processInfo.arguments.contains("UI-Testing")
}
}
private func setStateForUITesting() {
if AppDelegate.isUITestingEnabled {
UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
}
}
}
但是,如果UI测试需要解决方案#2设置的默认状态以外的状态怎么办? Bools默认为false
,Integers为0
,字符串为""
,但如果Bool键需要true
,该怎么办?
做这样的事情:
func testExample() {
app.launchEnvironment["UI-TestingKey_keepScreenOn"] = "YES"
app.launch()
}
然后在AppDelegate.swift
文件中:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
static let uiTestingKeyPrefix = "UI-TestingKey_"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if AppDelegate.isUITestingEnabled {
setUserDefaults()
}
return true
}
static var isUITestingEnabled: Bool {
get {
return ProcessInfo.processInfo.arguments.contains("UI-Testing")
}
}
private func setUserDefaults() {
for (key, value)
in ProcessInfo.processInfo.environment
where key.hasPrefix(AppDelegate.uiTestingKeyPrefix) {
// Truncate "UI-TestingKey_" part
let userDefaultsKey = key.truncateUITestingKey()
switch value {
case "YES":
UserDefaults.standard.set(true, forKey: userDefaultsKey)
case "NO":
UserDefaults.standard.set(false, forKey: userDefaultsKey)
default:
UserDefaults.standard.set(value, forKey: userDefaultsKey)
}
}
}
}
extension String {
func truncateUITestingKey() -> String {
if let range = self.range(of: AppDelegate.uiTestingKeyPrefix) {
let userDefaultsKey = self[range.upperBound...]
return String(userDefaultsKey)
}
return self
}
}
请注意,此示例仅适用于Bool和String键。 如果你需要更多的可伸缩性,应该修改switch命令以某种方式检查值是Integer还是Double或Any其他值,但总体思路就在这里。
编辑:从SwiftyUserDefaults 版本4.0.0-beta.1开始 ,使用解决方案#2和#3的原因似乎不再有效,因为他们通过启动参数添加了对设置值的支持。 但是,我不得不承认我之前没有测试过这个版本的SwiftyUserDefaults库,所以我会在这里保留两个解决方案。
通过UI测试,应用程序作为单独的进程运行。 您需要调用方法从应用程序本身清除NSUserDefaults。
我们的UI测试在启动应用程序时向应用程序传递了resetNSUserDefaults标志。 然后,应用程序会在启动过程的早期清除NSUserDefaults。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.