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

如何在Pytest钩子中实现iOS UI测试的重试逻辑?

在Pytest钩子中实现iOS UI测试的完整重试逻辑

要实现包含setup和teardown的完整测试重试流程,pytest_runtest_call钩子无法满足需求——它只能捕获测试执行阶段的异常,无法重新触发前后置流程。我们需要使用pytest_runtest_protocol钩子,它是控制整个测试生命周期的核心入口。

以下是不依赖第三方包的实现方案:

1. 实现重试逻辑处理器

先定义一个重试处理器,用于控制重试次数和判断逻辑:

class RetryLogicHandler:
    def __init__(self, max_retries=2):
        self.max_retries = max_retries
        # 记录每个测试用例的重试次数
        self.retry_counter = {}

    def should_retry(self, test_item):
        test_id = test_item.nodeid
        current_count = self.retry_counter.get(test_id, 0)
        if current_count < self.max_retries:
            self.retry_counter[test_id] = current_count + 1
            return True
        # 重置计数,避免影响后续运行
        self.retry_counter.pop(test_id, None)
        return False

# 初始化重试处理器,设置最大重试次数为2
retry_logic_handler = RetryLogicHandler(max_retries=2)

2. 重写测试执行协议钩子

在conftest.py中实现pytest_runtest_protocol钩子,替换测试的执行逻辑,注入重试:

def pytest_runtest_protocol(item, nextitem):
    # 保存原始的测试执行方法
    original_runtest = item.runtest

    def runtest_with_full_retry():
        last_exception = None
        while True:
            try:
                # 手动触发完整测试流程:setup → call → teardown
                item.runtest_setup()
                item.runtest_call()
                item.runtest_teardown()
                # 测试成功,执行预期失败验证
                _validate_expected_failures(None)
                break
            except Exception as exc:
                last_exception = exc
                # 判断是否需要重试
                if not retry_logic_handler.should_retry(item):
                    # 达到最大重试次数,执行预期失败验证并抛出异常
                    _validate_expected_failures((type(last_exception), last_exception, last_exception.__traceback__))
                    raise

    # 替换测试项的执行方法为带重试的版本
    item.runtest = runtest_with_full_retry

    # 返回None,让Pytest继续执行默认的测试协议流程
    return None

3. 适配原有预期失败验证逻辑

调整你的_validate_expected_failures函数,适配新的参数传递逻辑:

def _validate_expected_failures(excinfo):
    if excinfo:
        # 处理失败的测试用例,验证是否属于预期失败
        exc_type, exc_val, exc_tb = excinfo
        # 你的原有验证逻辑...
    else:
        # 处理成功的测试用例
        # 你的原有验证逻辑...

核心实现说明

  • 完整流程控制:通过手动调用runtest_setup()、runtest_call()、runtest_teardown(),确保每次重试都会执行完整的前后置操作,满足iOS UI测试重置状态的需求。
  • 重试计数管理:通过RetryLogicHandler的retry_counter字典,为每个测试用例独立记录重试次数,避免不同测试互相干扰。
  • 无第三方依赖:完全基于Pytest原生钩子实现,深入控制测试执行逻辑。

你可以根据需求扩展重试逻辑,比如:

  • 只针对特定标记的测试用例重试(通过item.get_closest_marker("retry")判断)
  • 只重试特定类型的异常(比如UI元素查找超时、App崩溃等)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:20:35