题目:UI 自动化用例偶发失败(网络抖动、元素偶现加载慢),团队想给用例加"失败自动重试"。请实现装饰器 retry:被装饰函数抛异常时最多重试 retries 次(含首次共 retries+1 次执行),重试间隔 delay 秒;全部失败后抛出最后一次的异常;成功则直接返回结果。
代码框架:
import time
def retry(retries=2, delay=1):
"""
@retry(retries=2, delay=1) 表示:失败后再试2次,每次间隔1秒
"""
# 请在此处补全
pass
# 测试:counter 记录执行次数,前两次抛异常,第三次成功
counter = {"n": 0}
@retry(retries=2, delay=0)
def flaky():
counter["n"] += 1
if counter["n"] < 3:
raise ValueError("flaky fail")
return "ok"
assert flaky() == "ok" and counter["n"] == 3
counter2 = {"n": 0}
@retry(retries=1, delay=0)
def always_fail():
counter2["n"] += 1
raise RuntimeError("boom")
try:
always_fail()
raised = False
except RuntimeError:
raised = True
assert raised and counter2["n"] == 2
难度:中级
题型:笔试(编程题)
参考答案/答题要点:
参考题解:
import time
from functools import wraps
def retry(retries=2, delay=1):
def deco(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(retries + 1):
try:
return func(*args, **kwargs)
except Exception:
if attempt == retries: # 最后一次机会也失败了
raise
time.sleep(delay)
return wrapper
return deco
采分点:①三层嵌套结构(装饰器工厂→deco→wrapper)写对,这是本题最大考点;②retries + 1 的执行次数语义;③最后一次失败要 raise 原异常,不能吞掉;④@wraps 保留函数名/docstring(pytest 用例名显示);⑤加分项:提"只对断言类异常重试、环境错误(找不到元素属于 setup 问题)不该重试"、“配合 pytest-rerunfailures 做用例级重试”。