pytest失败时触发截图需在pytest_runtest_makereport钩子中,检查report.when=="call"且report.failed为真,通过autouse fixture将driver绑定到item.driver,再调用driver.get_screenshot_as_file()保存带时间戳、用例名和错误摘要的唯一文件。

pytest 失败时怎么触发截图逻辑
关键不是“自动”,而是利用 pytest 的 pytest_runtest_makereport 钩子捕获测试状态,再在 pytest_exception_interact 或 pytest_runtest_makereport 里调用 Selenium 的 screenshot() 方法。失败判定必须基于 report.failed(不是 report.when == "call" 就够),且仅对 UI 测试用例生效——否则会干扰纯单元测试。
- 必须检查
report.when == "call"且report.failed同时为真,否则 setup/teardown 失败也会误截 - 截图前要确保 WebDriver 实例还活着(
driver.session_id存在且未抛WebDriverException) - 推荐把 driver 存在 fixture 作用域中(如
scope="function"),避免在钩子里去全局找 driver 对象
如何把 driver 实例传进 pytest 钩子函数
pytest 钩子本身不接收 fixture,所以不能直接写 def pytest_runtest_makereport(item, call, report, driver)。正确做法是:在测试函数执行前,把 driver 绑定到 item 对象上,钩子中再从 item 取出。
- 在 conftest.py 中定义一个 autouse fixture,比如
attach_driver_to_item,它接收driver和request,然后执行request.node.driver = driver - 钩子函数里用
if hasattr(report.node, "driver"):判断是否存在 driver,再调用report.node.driver.get_screenshot_as_file(...) - 不要用
globals()或模块级变量存 driver,多线程/并发运行时会错乱
截图文件名怎么带时间、用例名、失败信息
文件名必须唯一、可追溯,否则重跑测试会覆盖。建议组合:用例节点 ID + 时间戳 + 简化错误消息(去掉换行和特殊字符)。
- 用
report.node.name.replace("[", "_").replace("]", "_")清洗节点名 - 用
datetime.now().strftime("%Y%m%d_%H%M%S")生成时间戳 - 错误摘要取
report.longreprtext.splitlines()[0][:50],避免文件名过长或含非法字符 - 路径建议写入
./screenshots/并提前os.makedirs("./screenshots", exist_ok=True)
为什么截图经常报 WebDriverException 或空白图
最常见原因是 driver 已关闭但钩子还在尝试截图——比如测试里显式调了 driver.quit(),或异常导致 teardown 提前执行。另一个原因是截图发生在新窗口/iframe 上下文里,而 driver 当前不在主文档。
立即学习“Python免费学习笔记(深入)”;
- 在截图前加一层保护:
try: driver.get_screenshot_as_file(path) except WebDriverException: pass - 截图前确保回到默认内容:
driver.switch_to.default_content(),并忽略 iframe 切换异常 - 如果用的是 headless 模式,确认已设置
--no-sandbox --disable-dev-shm-usage,否则 Chromium 可能无法渲染画面


















