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

如何在UI测试启动前修改Xcode并行测试克隆模拟器状态栏

实现方法

不要依赖Scheme的Pre-action触发逻辑,直接把状态栏修改逻辑绑定到XCTest的生命周期节点即可,这个节点恰好满足「克隆模拟器启动完成、正式测试逻辑未执行」的时机要求。

方案1:测试基类类层级setUp触发(零额外配置,最稳定)

这是成本最低、兼容性最好的实现方式:

  • 每个UI测试类执行第一个用例前,一定会调用类方法setUp(),此时Xcode已经完成当前测试任务对应克隆模拟器的创建、启动流程,设备处于可交互状态。
  • 测试运行时会自动注入当前绑定模拟器的UDID到环境变量SIMULATOR_UDID,不需要手动遍历查询所有克隆设备,直接读取就能精准操作当前测试对应的模拟器,不会干扰其他并行测试的实例。

直接把以下代码放到你的UI测试全局基类里即可:

override class func setUp() {
    super.setUp()
    
    guard let targetSimUDID = ProcessInfo.processInfo.environment["SIMULATOR_UDID"] else {
        return
    }
    
    let statusBarConfigTask = Process()
    statusBarConfigTask.launchPath = "/usr/bin/xcrun"
    // 按需修改你需要的状态栏参数即可
    statusBarConfigTask.arguments = [
        "simctl", "--set", "testing", "status_bar", targetSimUDID, "override",
        "--time", "9:41",
        "--dataNetwork", "wifi",
        "--wifiBars", "3",
        "--batteryState", "charged",
        "--batteryLevel", "100"
    ]
    try? statusBarConfigTask.run()
    statusBarConfigTask.waitUntilExit()
}

注意必须使用类层级的class func setUp(),不要用实例层级的setUp(),前者只会在当前类所有用例执行前运行一次,不会重复执行修改逻辑,执行效率更高。

方案2:全局测试观察器(适合多模块测试复用)

如果测试类分散在多个模块、不想每个测试基类都重复加这段逻辑,可以注册全局XCTest监听:

  • 新建一个遵循XCTestObservation协议的监听类,在testBundleWillStart(_:)回调中实现上述状态栏修改逻辑
  • 在测试Bundle加载阶段(比如OC的+load方法、Swift的@objc初始化逻辑)注册这个观察器即可
    这个触发时机比类层级setUp更早,同样满足时机要求。

注意事项

  • 不要尝试在CI脚本或者Scheme Pre-action里轮询等待克隆模拟器生成:并行测试的克隆实例是Xcode动态调度创建的,提前轮询稳定性极差,还可能误改其他并行测试任务对应的模拟器状态。
  • 所有操作克隆模拟器的simctl命令必须携带--set testing参数,克隆模拟器不会出现在默认设备集中,不带该参数会报设备不存在的错误。
  • 建议把修改逻辑放在super.setUp()调用之后执行,确保测试运行器已经和模拟器完成通信连接,避免偶发的命令执行不生效问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:01:40