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

iOS Swift:提升TableView Cell中UI测试按钮点击稳定性

问题:提升iOS Swift中TableView单元格内按钮UI测试稳定性

本地重复运行100次均稳定通过的UI测试,在CI环境下出现Flaky(不稳定)问题。测试流程为点击TableView中第一个Pay按钮触发弹窗,随后断言弹窗存在,但CI中偶尔会出现tap()操作无法触发按钮的情况,导致弹窗未出现,最终断言失败。怀疑问题根源在AccountDetailsScreen.swift中payButton的声明逻辑。

相关代码

AccountDetailsUITests.swift

import XCTest

class AccountDetailsTests: UITestBaseTestCase {
    
    func testAccountDetailsAlertForPayButton() throws {
        try setupAndPrepare()

        TransactionsFlow().showTransactions(for: Fixtures.account)

        let accountDetailsScreen = AccountDetailsScreens.TransactionsList().waitUntilReady()

        sleep(forTimeInterval: 0.3)
        accountDetailsScreen.payButton.tap()
        assertElementExists(accountDetailsScreen.payAlertView, timeout: 10)
        accountDetailsScreen.oKAlertButton.tap()
     }
} 

AccountDetailsScreen.swift

import XCTest

class AccountDetailsScreens: BaseScreen {
   // Other Code
   class TransactionsList: BaseScreen {
     var payButton: XCUIElement {
            app.cells.containing(.button, identifier: "TilePayButton").firstMatch.buttons["TilePayButton"]
     }
     lazy var oKAlertButton = app.alerts.buttons["okayButtonCollectionAlertAccountDetails"]
     lazy var payAlertView = app.alerts["payAlertView"]
   }
}

优化方案

1. 修正payButton定位逻辑

原嵌套查找方式(先找含按钮的cell再取按钮)容易出现匹配偏差,可简化定位逻辑:

var payButton: XCUIElement {
    // 直接定位可见区域内的第一个Pay按钮
    app.buttons["TilePayButton"].firstMatch
}

若需限定在cell内,可优化为:

var payButton: XCUIElement {
    let firstCell = app.cells.firstMatch
    XCTAssertTrue(firstCell.waitForExistence(timeout: 5))
    return firstCell.buttons["TilePayButton"]
}

2. 替换固定等待为显式等待

测试中的sleep(forTimeInterval: 0.3)是固定等待,CI环境资源波动时可能不足以让元素就绪,替换为等待按钮可交互:

let payButton = accountDetailsScreen.payButton
// 等待按钮存在且可点击
XCTAssertTrue(payButton.waitForExistence(timeout: 5))
XCTAssertTrue(payButton.isHittable)
payButton.tap()

3. 增强点击可靠性

若直接tap()偶尔失效,可尝试坐标点击或添加重试逻辑:

// 方案1:点击按钮中心坐标
payButton.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()

// 方案2:最多重试3次点击
var alertAppeared = false
for _ in 1...3 {
    payButton.tap()
    if accountDetailsScreen.payAlertView.waitForExistence(timeout: 2) {
        alertAppeared = true
        break
    }
}
XCTAssertTrue(alertAppeared, "点击Pay按钮后弹窗未出现")

4. 完善屏幕就绪判断

确保waitUntilReady()真正等待按钮加载完成,可在TransactionsList类中重写该方法:

override func waitUntilReady() -> Self {
    super.waitUntilReady()
    XCTAssertTrue(payButton.waitForExistence(timeout: 10))
    return self
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:06:35