Pytest结合Selenium实现失败截图触发Class无rep_call属性报错
问题成因
你遇到的AttributeError: 'Class' object has no attribute 'rep_call'本质原因有两点:
rep_call不是pytest原生自动挂载到测试节点上的属性:这个对象是pytest测试执行报告的实例,需要通过自定义钩子主动生成并绑定到测试节点上,默认情况下request.node上不存在这个属性,直接访问就会抛出属性不存在的错误。- 混淆了fixture后置逻辑和pytest报告钩子的执行时序:fixture的yield后置逻辑虽然会在测试方法执行完成后运行,但它本身无法感知测试方法的执行结果,必须通过钩子提前把测试结果存到节点上,fixture里才能读取到。
修复方案
按两步调整即可实现测试失败自动截图的逻辑:
第一步:注册pytest报告钩子,绑定测试执行结果到测试节点
把以下代码放到项目根目录的conftest.py文件中,让pytest在生成测试执行报告时,自动把分阶段的报告对象存到对应测试节点上:
import pytest @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): # 等待所有钩子执行完成,获取最终的测试报告 outcome = yield report = outcome.get_result() # 按测试阶段(setup/call/teardown)把报告绑定到测试节点属性上 setattr(item, f"rep_{report.when}", report)
第二步:优化原有的driver_init fixture逻辑
去掉原代码中冗余的addfinalizer逻辑,统一用yield后置流程处理驱动退出、截图采集的逻辑,同时加属性存在性校验避免报错:
import allure from selenium import webdriver @pytest.fixture(scope="class") def driver_init(request): # 初始化浏览器驱动 driver = webdriver.Chrome() # 把驱动实例挂载到测试类,方便测试方法直接调用 request.cls.driver = driver yield driver # 仅当测试方法(call阶段)执行失败时采集截图 if hasattr(request.node, "rep_call") and request.node.rep_call.failed: try: screenshot_png = driver.get_screenshot_as_png() allure.attach( screenshot_png, name=f"失败截图_{request.function.__name__}", attachment_type=allure.attachment_type.PNG ) except Exception as e: # 可选:打印截图采集的异常信息,避免静默吞错 print(f"自动采集失败截图时出现异常: {str(e)}") # 统一在流程最后退出驱动 driver.quit()
常见踩坑提醒
- 不要把报告钩子写在单个测试文件里,必须放在conftest.py中保证全局加载,否则局部文件加载时序晚于fixture的话,依然会出现属性不存在的问题。
- 不要用裸
except吞掉所有异常,否则截图失败、驱动异常的问题会被完全隐藏,排查问题时没有任何日志提示。 - 不需要混用
addfinalizer和yield两种fixture后置逻辑,两种机制的执行顺序可能出现错乱,统一用yield后置代码块维护流程即可。
内容的提问来源于stack exchange,提问作者izotop
相关产品推荐
相关产品推荐

