使用自定义Playwright-Python浏览器上下文,如何用Pytest捕获失败用例截图?
问题:Playwright-Python类结构结合pytest实现失败截图
刚接触测试自动化,用Playwright-Python为团队SaaS门户写测试,采用类结构封装Playwright操作,但当前类在__init__中自行初始化sync_playwright、browser、context和page,导致无法在pytest的conftest.py中获取page对象实现失败截图功能。核心需求是捕获失败用例的截图。
原测试代码(sauceAutomation.py):
from playwright.sync_api import Playwright, Page, expect, sync_playwright import time class SaucyAutomation: def __init__(self): self.playwright = sync_playwright().start() self.browser = self.playwright.chromium.launch(headless=False,args=["--start-maximized"]) self.context = self.browser.new_context(no_viewport=False) self.page = self.context.new_page() self.environment = None def login(self, username, password): self.page.goto("https://www.saucedemo.com/") self.page.locator("//input[@id='user-name']").fill(username) self.page.locator("//input[@id='password']").fill(password) self.page.locator("//input[@id='login-button']").click() def burgerNavigate(self,menuItem): self.page.locator("//button[@id='react-burger-menu-btn']").click() self.page.locator("//a[@id='" + menuItem + "']").click() def logout(self): self.burgerNavigate("logout_sidebar_link") def test_LoginLogout(): sauceDemo = SaucyAutomation() sauceDemo.login("standard_user", "secret_sauce") time.sleep(2) sauceDemo.logout()
尝试的conftest.py无法正常获取page对象,截图逻辑无法执行。
解决方案
1. 重构测试类,依赖pytest的page fixture
把类的初始化改为接收外部传入的page对象,不再自行创建Playwright实例,适配pytest的fixture体系:
修改后的sauceAutomation.py:
from playwright.sync_api import Page, expect import time class SaucyAutomation: def __init__(self, page: Page): self.page = page self.environment = None def login(self, username, password): self.page.goto("https://www.saucedemo.com/") self.page.locator("//input[@id='user-name']").fill(username) self.page.locator("//input[@id='password']").fill(password) self.page.locator("//input[@id='login-button']").click() def burgerNavigate(self,menuItem): self.page.locator("//button[@id='react-burger-menu-btn']").click() self.page.locator("//a[@id='" + menuItem + "']").click() def logout(self): self.burgerNavigate("logout_sidebar_link") def test_LoginLogout(page): sauceDemo = SaucyAutomation(page) sauceDemo.login("standard_user", "secret_sauce") time.sleep(2) sauceDemo.logout()
2. 完善conftest.py,实现失败截图逻辑
配置Playwright的fixture,并在测试失败时自动截图:
import os import pytest from playwright.sync_api import sync_playwright @pytest.fixture(scope="function") def page(): with sync_playwright() as playwright: browser = playwright.chromium.launch(headless=False, args=["--start-maximized"]) context = browser.new_context(no_viewport=False) page = context.new_page() yield page # 测试结束后自动清理资源 context.close() browser.close() @pytest.hookimpl(tryfirst=True, wrapper=True) def pytest_runtest_makereport(item, call): # 获取测试报告对象 rep = yield # 仅处理测试执行阶段的失败用例 if rep.when == "call" and rep.failed: # 创建screenshots目录(不存在则自动生成) screenshot_dir = "screenshots" os.makedirs(screenshot_dir, exist_ok=True) # 生成唯一的截图文件名,避免冲突 screenshot_path = os.path.join( screenshot_dir, f"{item.nodeid.replace('/', '_').replace('::', '_')}.png" ) # 从fixture中获取page对象并生成全屏截图 page = item.funcargs["page"] page.screenshot(path=screenshot_path, full_page=True) # 若使用pytest-html,将截图嵌入测试报告 pytest_html = item.config.pluginmanager.getplugin("html") if pytest_html: extra = getattr(rep, "extras", []) extra.append(pytest_html.extras.image(screenshot_path)) rep.extras = extra return rep
3. 运行测试
执行命令:
pytest sauceAutomation.py --html=report.html
关键说明
- 测试类不再自行管理Playwright生命周期,通过pytest fixture注入page对象,确保conftest能获取到有效page实例
- page fixture的scope设为
function,每个测试用例创建独立page,避免测试间状态污染 - 截图逻辑仅在测试失败时触发,自动保存到
screenshots目录,同时支持将截图嵌入pytest-html报告
内容的提问来源于stack exchange,提问作者peyt1212
相关产品推荐
相关产品推荐

