如何在Python Playwright异步测试中共享Page对象以提速?
问题描述
我刚接触Python Playwright测试,正尝试将现有TypeScript Playwright测试迁移至Python版本。目前运行3个仅访问Playwright官网并打印页面标题的基础异步测试耗时约50秒,同步方式使用Page对象可将耗时降至30秒,但异步方式无法直接复用Page对象。
异步实现代码:
from playwright.async_api import async_playwright def test_has_title(): with async_playwright() as p: browser = p.chromium.launch() context = browser.new_context() page = context.new_page() # Go to the Playwright documentation page page.goto("https://playwright.dev/") print(page.title())
同步复用Page对象的代码:
from playwright.sync_api import Page def test_has_title(page: Page): page.goto("https://playwright.dev/") print(page.title())
尝试的异步复用Page对象代码(无法正常工作):
import pytest from playwright.async_api import Page @pytest.mark.asyncio async def test_has_title(page: Page): await page.goto("https://playwright.dev/") print(await page.title())
使用的包版本:
playwright 1.51.0 pytest 8.3.5 pytest-asyncio 0.26.0 pytest-base-url 2.1.0 pytest-dotenv 0.5.2 pytest-playwright 0.7.0
请问如何在多个异步测试中共享Page对象以加快测试执行速度?
解决方案
要在异步测试中复用Page对象,核心是利用pytest的fixture作用域控制browser、context和page的生命周期,避免每个测试重复启动浏览器、创建上下文。
方法1:正确使用pytest-playwright内置异步fixture
pytest-playwright本身提供异步版本的page fixture,你之前的代码问题在于没结合pytest的异步fixture机制。修正后测试代码如下:
import pytest from playwright.async_api import Page @pytest.mark.asyncio async def test_has_title(page: Page): await page.goto("https://playwright.dev/") title = await page.title() print(title) @pytest.mark.asyncio async def test_has_title_2(page: Page): await page.goto("https://playwright.dev/python") title = await page.title() print(title)
默认page fixture作用域为function(每个测试创建新页面),如果想进一步复用资源,可自定义fixture调整作用域。
方法2:自定义全局共享的Page fixture
如果所有测试无状态依赖,可创建作用域为session或module的fixture,让所有测试共用同一个Page对象:
import pytest from playwright.async_api import async_playwright @pytest.fixture(scope="session") async def shared_page(): async with async_playwright() as p: browser = await p.chromium.launch() context = await browser.new_context() page = await context.new_page() yield page # 测试结束后清理资源 await page.close() await context.close() await browser.close() @pytest.mark.asyncio async def test_has_title(shared_page): await shared_page.goto("https://playwright.dev/") print(await shared_page.title()) @pytest.mark.asyncio async def test_has_title_2(shared_page): await shared_page.goto("https://playwright.dev/python") print(await shared_page.title())
方法3:共享Browser Context(更推荐)
直接共享Page易引发测试状态冲突,更稳妥的方式是共享Browser Context,每个测试创建独立Page:
import pytest from playwright.async_api import async_playwright @pytest.fixture(scope="session") async def shared_context(): async with async_playwright() as p: browser = await p.chromium.launch() context = await browser.new_context() yield context await context.close() await browser.close() @pytest.fixture(scope="function") async def page(shared_context): page = await shared_context.new_page() yield page await page.close() @pytest.mark.asyncio async def test_has_title(page): await page.goto("https://playwright.dev/") print(await page.title()) @pytest.mark.asyncio async def test_has_title_2(page): await page.goto("https://playwright.dev/python") print(await page.title())
关键注意事项
- 异步代码必须全程使用
await,包括所有Playwright API调用(如page.goto、page.title) - 共享Page时,需确保测试间无状态依赖(比如不要在一个测试中修改页面URL、填写表单后,另一个测试依赖该状态)
- 优先选择共享Context而非Page,既能提升执行速度,又能降低测试间的干扰
内容的提问来源于stack exchange,提问作者PersonaVeratis
相关产品推荐
相关产品推荐

