You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 09:37:20