普通视图

发现新文章,点击刷新页面。
今天 — 2025年7月6日首页

Playwright 中 Page 对象的常用方法详解

2025年7月6日 08:26

Page 对象是 Playwright 的核心 API 之一,代表浏览器中的一个标签页或弹出窗口。以下是 Page 对象最常用的方法及其使用示例和运行原理。

1. 导航相关方法

goto(url)

作用:导航到指定 URL
原理:等待页面加载到网络空闲状态(load 事件触发)

await page.goto("https://example.com")
# 同步方式
page.goto("https://example.com")

reload()

作用:重新加载当前页面
原理:触发页面刷新,等待新页面加载完成

await page.reload()
# 可带选项
await page.reload(timeout=5000, wait_until="networkidle")

go_back() / go_forward()

作用:前进/后退导航
原理:模拟浏览器前进后退按钮行为

await page.go_back()
await page.go_forward()

2. 元素定位与交互

locator(selector)

作用:创建元素定位器
原理:返回一个 Locator 对象,不立即查询 DOM

button = page.locator("button.submit")
# 推荐使用更语义化的定位方式
button = page.get_by_role("button", name="Submit")

click(selector)

作用:点击指定元素
原理:执行可操作性检查后触发点击事件

await page.click("#submit-btn")
# 带选项
await page.click("button", force=True, timeout=5000)

fill(selector, value)

作用:填充表单字段
原理:先清除字段再输入值,触发适当事件

await page.fill("#username", "testuser")

type(selector, text)

作用:模拟键盘输入
原理:逐个字符触发键盘事件

await page.type("#search", "Playwright", delay=100)  # 带输入延迟

3. 页面内容操作

evaluate(expression)

作用:在页面上下文中执行 JavaScript
原理:在浏览器环境中执行脚本并返回结果

title = await page.evaluate("document.title")
# 传参数
result = await page.evaluate("(arg) => window.myFunction(arg)", arg_value)

content()

作用:获取页面完整 HTML
原理:返回当前 DOM 的序列化 HTML

html = await page.content()

set_content(html)

作用:设置页面 HTML 内容
原理:替换当前文档内容,不触发网络请求

await page.set_content("<h1>Test Page</h1>")

4. 等待与断言

wait_for_selector(selector)

作用:等待元素出现
原理:轮询 DOM 直到元素存在

await page.wait_for_selector(".loading-spinner", state="hidden")

wait_for_event(event)

作用:等待特定事件
原理:监听页面事件,返回 Promise

async with page.expect_event("popup") as popup_info:
    await page.click("#popup-link")
popup = await popup_info.value

wait_for_timeout(ms)

作用:强制等待
原理:不推荐使用,除非绝对必要

await page.wait_for_timeout(1000)  # 等待1秒

5. 页面管理

screenshot()

作用:截取页面截图
原理:捕获当前视口或全屏

await page.screenshot(path="screenshot.png", full_page=True)

pdf()

作用:生成 PDF
原理:打印当前页面为 PDF(仅限 Chromium)

await page.pdf(path="output.pdf")

close()

作用:关闭页面
原理:触发页面卸载过程

await page.close()

6. 对话框处理

on(event, handler)

作用:监听对话框事件
原理:注册事件处理函数

page.on("dialog", lambda dialog: dialog.accept())

expect_dialog()

作用:等待对话框出现
原理:返回上下文管理器处理对话框

async with page.expect_dialog() as dialog_info:
    await page.click("#trigger-alert")
dialog = await dialog_info.value

7. 框架处理

frame(name)

作用:获取指定 iframe
原理:返回 Frame 对象用于操作 iframe 内容

frame = page.frame("login-frame")
await frame.fill("#username", "admin")

8. 浏览器上下文

context

作用:获取所属浏览器上下文
原理:返回创建该页面的 BrowserContext

context = page.context
cookies = await context.cookies()

运行原理总结

  1. 自动等待:大多数操作会自动等待元素可操作
  2. 事件驱动:基于浏览器事件循环响应各种页面事件
  3. 智能重试:操作失败时会自动重试直到超时
  4. 沙盒环境:每个测试运行在独立环境中,互不影响

最佳实践示例

async def test_complete_flow(page):
    # 导航
    await page.goto("https://shop.example.com")
    
    # 等待元素
    await page.wait_for_selector("#products")
    
    # 定位与交互
    await page.get_by_role("link", name="Login").click()
    await page.fill("#username", "testuser")
    await page.fill("#password", "password123")
    await page.click("#login-btn")
    
    # 断言
    await expect(page).to_have_url("https://shop.example.com/dashboard")
    await expect(page.get_by_text("Welcome, testuser")).to_be_visible()
    
    # 处理对话框
    page.on("dialog", lambda dialog: dialog.accept())
    await page.click("#logout-btn")
    
    # 截图
    await page.screenshot(path="after_login.png")

这些方法覆盖了 Page 对象 80% 以上的日常使用场景,掌握它们可以高效完成大多数 Web 自动化测试任务。

昨天 — 2025年7月5日首页

Playwright 中特定的 Fixtures

2025年7月5日 17:33

Playwright 为 pytest 提供了一组专门的 fixtures,用于简化浏览器自动化测试的编写。这些 fixtures 管理浏览器、上下文和页面的生命周期,让测试更加简洁高效。

常用 Playwright Fixtures 列表

以下是 Playwright 最常用的 pytest fixtures:

  1. playwright - Playwright 实例
  2. browser - 浏览器实例
  3. browser_name - 当前浏览器名称
  4. browser_channel - 浏览器渠道
  5. context - 浏览器上下文
  6. page - 页面实例
  7. is_webkit, is_firefox, is_chromium - 浏览器类型检查

安装和配置

首先需要安装必要的包:

pip install pytest-playwright
playwright install

各 Fixture 详解及示例

1. playwright fixture

作用:提供 Playwright 的初始实例

示例

def test_with_playwright(playwright):
    chromium = playwright.chromium
    browser = chromium.launch()
    # 测试代码...
    browser.close()

原理:管理 Playwright 的启动和清理,是其他浏览器相关 fixtures 的基础

2. browser fixture

作用:提供已启动的浏览器实例

示例

def test_with_browser(browser):
    page = browser.new_page()
    page.goto("https://example.com")
    assert "Example" in page.title()

原理

  • 测试开始时自动启动浏览器
  • 测试结束后自动关闭浏览器
  • 默认使用 Chromium,可通过命令行参数更改

3. browser_name fixture

作用:获取当前测试使用的浏览器名称

示例

def test_browser_name(browser, browser_name):
    print(f"Running test on {browser_name}")
    assert browser_name in ["chromium", "firefox", "webkit"]

4. context fixture

作用:提供浏览器上下文实例

示例

def test_with_context(context):
    page = context.new_page()
    page.goto("https://example.com")
    assert page.url == "https://example.com/"

原理

  • 浏览器上下文相当于一个独立的浏览器会话
  • 隔离 cookies 和本地存储
  • 测试结束后自动关闭

5. page fixture (最常用)

作用:提供已创建的页面实例

示例

def test_example(page):
    page.goto("https://example.com")
    heading = page.get_by_role("heading", name="Example Domain")
    assert heading.is_visible()

原理

  • 每个测试自动创建新页面
  • 测试结束后自动关闭页面
  • 包含所有常用的页面操作方法

高级配置示例

自定义浏览器选项

conftest.py 中:

import pytest

@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
    return {
        **browser_context_args,
        "viewport": {"width": 1920, "height": 1080},
        "ignore_https_errors": True
    }

多浏览器测试

运行不同浏览器的测试:

pytest --browser chromium --browser firefox --browser webkit

对应的测试文件:

def test_multi_browser(page, browser_name):
    page.goto("https://example.com")
    if browser_name == "firefox":
        # Firefox 特定的断言
        pass
    elif browser_name == "webkit":
        # WebKit 特定的断言
        pass

Fixture 作用域控制

Playwright fixtures 默认作用域是"function"(每个测试函数一个实例),但可以调整:

@pytest.fixture(scope="module")
def shared_page(page):
    # 这个 page 将在整个模块中共享
    yield page

运行原理

  1. 初始化阶段

    • playwright fixture 初始化 Playwright 实例
    • browser fixture 使用 Playwright 实例启动浏览器
    • context fixture 创建浏览器上下文
    • page fixture 在上下文中创建新页面
  2. 测试执行阶段

    • 测试函数接收配置好的 page 或其他 fixtures
    • 执行测试逻辑
  3. 清理阶段

    • 按照创建的反向顺序自动清理资源
    • 先关闭 page,然后 context,最后 browser

最佳实践

  1. 大多数测试只需使用 page fixture
  2. 需要特殊配置时才使用底层 fixtures
  3. 使用 browser_context_args 定制默认上下文设置
  4. 对于需要登录的测试,可以创建自定义 fixture 重用认证状态
@pytest.fixture
def authenticated_page(page):
    page.goto("/login")
    page.fill("#username", "testuser")
    page.fill("#password", "password")
    page.click("text=Sign in")
    # 确保登录成功
    assert page.url == "/dashboard"
    return page

def test_dashboard(authenticated_page):
    authenticated_page.goto("/dashboard")
    # 测试代码...
❌
❌