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

XCUI测试失败后如何继续执行后续BundleID的检测循环?

解决XCTest断言失败后终止循环的问题

核心原因

XCTest的XCTAssert系列断言失败时会抛出异常,若未做处理或continueAfterFailure设为false,会直接终止当前测试方法执行,导致后续BundleID检测中断。另外你手动调用setUp()和tearDown()的方式不符合XCTest生命周期规范,易引发状态混乱。

解决方案

方案1:捕获异常+记录失败,保持循环执行

通过do-catch捕获每个Bundle测试的异常,将失败记录到对应测试活动中,确保循环继续执行下一个Bundle。

修改后的完整代码:

class YourTestCase: XCTestCase {
    override func setUp() {
        super.setUp()
        // 此处放测试方法通用初始化逻辑,无需手动调用
    }
    
    override func tearDown() {
        super.tearDown()
        // 此处放测试方法通用清理逻辑,无需手动调用
    }
    
    func testLaunchApp() {
        let bundles = ["com.App1", "com.App2", "com.App3", "com.App4"]
        // 强制开启失败后继续执行的逻辑
        continueAfterFailure = true
        
        for bundle in bundles {
            XCContext.runActivity(named: "Test launching \(bundle)") { activity in
                self.resetTestEnvironment()
                
                do {
                    try self.testBundleForButton(bundle: bundle)
                } catch {
                    activity.recordFailure(
                        withDescription: error.localizedDescription,
                        inFile: #file,
                        atLine: #line,
                        expected: true
                    )
                }
            }
        }
    }
    
    // 自定义测试方法,抛出错误替代直接断言
    private func testBundleForButton(bundle: String) throws {
        let app = XCUIApplication(bundleIdentifier: bundle)
        app.launch()
        
        let theButton = app.button["myButton"]
        let isVisible = theButton.waitForExistence(timeout: 1)
        
        guard isVisible else {
            throw NSError(
                domain: "BundleTestError",
                code: 1,
                userInfo: [NSLocalizedDescriptionKey: "Button 'myButton' not found in bundle \(bundle)"]
            )
        }
    }
    
    // 自定义环境重置方法,替代手动调用setUp/tearDown
    private func resetTestEnvironment() {
        // 终止当前所有打开的应用
        XCUIApplication().terminate()
        // 可添加其他状态重置逻辑,如模拟器设置恢复等
    }
}

方案2:简化版——直接开启失败后续执行

若想保留XCTAssert,只需显式设置continueAfterFailure = true,同时去掉手动调用的setUp()/tearDown(),并在每个Bundle测试前清理环境:

简化代码:

func testLaunchApp() {
    let bundles = ["com.App1", "com.App2", "com.App3", "com.App4"]
    // 关键配置:断言失败后继续执行后续逻辑
    continueAfterFailure = true
    
    for bundle in bundles {
        XCContext.runActivity(named: "Test launching \(bundle)") { activity in
            // 先终止上一个测试的应用,避免状态干扰
            XCUIApplication().terminate()
            
            let app = XCUIApplication(bundleIdentifier: bundle)
            app.launch()
            
            let theButton = app.button["myButton"]
            let isVisible = theButton.waitForExistence(timeout: 1)
            // 断言失败会记录但不会终止循环
            XCTAssert(isVisible, "Button 'myButton' not found in bundle \(bundle)")
        }
    }
}

关键注意事项

  • 禁止手动调用setUp()/tearDown():这两个方法由XCTest框架自动管理,每个测试方法前后各执行一次,手动调用会导致状态异常。
  • 显式设置continueAfterFailure = true:不同Xcode版本默认值可能不同,显式设置可确保断言失败后继续执行。
  • 每个Bundle测试前清理环境:务必终止当前应用,避免不同Bundle的应用状态互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:53:27