You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在UI测试中设置UserDefaults初始值并允许后续修改?

解决UserDefaults测试初始值与后续修改冲突的问题

问题核心

通过XCUIApplication.launchArguments直接覆盖UserDefaults键值后,应用后续对该键的修改会被忽略——这是因为launchArguments传入的键值会被放到UserDefaults的注册域,优先级高于应用自身的持久化域,导致后续修改的持久化值不会被读取。

针对你的两个测试需求,以下是原生Swift环境下的解决方案:


场景1:验证首次启动的默认值设置逻辑

要模拟首次启动(UserDefaults键值为nil),同时确保后续可修改,不能直接用launchArguments覆盖键值,而是通过传入标记参数让应用自行初始化。

步骤1:修改应用内的启动逻辑(SceneDelegate)

在scene(_:willConnectTo:options:)中添加测试标记的处理逻辑:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    let userDefaults = UserDefaults.standard
    let launchArgs = ProcessInfo.processInfo.arguments
    
    // 处理测试标记
    if launchArgs.contains("TEST_FIRST_LAUNCH") {
        // 删除键值,模拟首次启动的nil状态
        userDefaults.removeObject(forKey: "showClockTime")
    }
    
    // 原有默认值设置逻辑保持不变
    if userDefaults.object(forKey: "showClockTime") == nil {
        userDefaults.set(true, forKey: "showClockTime")
    }
    
    // 其他界面初始化逻辑...
}

步骤2:编写测试用例

func testFirstLaunchSetsDefaultValue() {
    let app = XCUIApplication()
    app.launchArguments.append("TEST_FIRST_LAUNCH")
    app.launch()
    
    // 验证UI是否按showClockTime=true渲染(替换成你的实际UI元素判断)
    XCTAssertTrue(app.staticTexts["3:00pm"].exists)
    
    // 验证UserDefaults最终值为true
    let userDefaults = UserDefaults.standard
    XCTAssertEqual(userDefaults.bool(forKey: "showClockTime"), true)
}

场景2:设置初始测试值并验证修改功能

要确保测试开始时UserDefaults有指定初始值,同时允许应用后续修改,同样通过启动标记让应用自行设置持久化域的初始值。

步骤1:扩展SceneDelegate的测试标记处理

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    let userDefaults = UserDefaults.standard
    let launchArgs = ProcessInfo.processInfo.arguments
    
    if launchArgs.contains("TEST_FIRST_LAUNCH") {
        userDefaults.removeObject(forKey: "showClockTime")
    } else if launchArgs.contains("TEST_INIT_SHOW_CLOCK_TRUE") {
        // 设置初始值为true,写入持久化域
        userDefaults.set(true, forKey: "showClockTime")
    }
    
    // 原有默认值设置逻辑
    if userDefaults.object(forKey: "showClockTime") == nil {
        userDefaults.set(true, forKey: "showClockTime")
    }
    
    // 其他初始化逻辑...
}

步骤2:编写修改验证测试用例

func testSettingsToggleUpdatesUserDefaults() {
    let app = XCUIApplication()
    app.launchArguments.append("TEST_INIT_SHOW_CLOCK_TRUE")
    app.launch()
    
    // 进入设置页
    app.buttons["设置"].tap()
    
    // 切换开关至关闭状态
    app.switches["显示具体时间"].tap()
    
    // 返回主界面验证UI更新
    app.navigationBars["设置"].buttons["返回"].tap()
    XCTAssertTrue(app.staticTexts["1小时后"].exists)
    
    // 验证UserDefaults已被修改为false
    let userDefaults = UserDefaults.standard
    XCTAssertEqual(userDefaults.bool(forKey: "showClockTime"), false)
}

额外优化:保证测试独立性

为避免测试间的UserDefaults持久化影响,在测试类的setUp方法中重置相关键值:

override func setUp() {
    super.setUp()
    continueAfterFailure = false
    
    let userDefaults = UserDefaults.standard
    // 清除所有测试相关的UserDefaults键
    userDefaults.removeObject(forKey: "showClockTime")
    userDefaults.synchronize()
}

内容的提问来源于stack exchange,提问作者Kay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:21:10