Anthropic Skills 中文文档
首页
使用指南
技能列表
  • 🎨 创意与设计
  • 💻 开发与技术
  • 🏢 企业与沟通
  • 📄 文档处理
  • 🔧 元技能
  • GitHub 仓库
  • Claude 官网
  • Skills 官方文档
GitHub
首页
使用指南
技能列表
  • 🎨 创意与设计
  • 💻 开发与技术
  • 🏢 企业与沟通
  • 📄 文档处理
  • 🔧 元技能
  • GitHub 仓库
  • Claude 官网
  • Skills 官方文档
GitHub
  • 技能列表
  • 🎨 创意与设计

    • 🎨 算法艺术生成

      • 📋 概览
      • 📖 完整指南
    • 🖼️ 画布设计

      • 📋 概览
      • 📖 完整指南
    • 🎬 Slack GIF 创建器

      • 📋 概览
      • 📖 完整指南
    • 🎨 主题工厂

      • 📋 概览
      • 📖 完整指南
  • 💻 开发与技术

    • 🎨 Web 组件构建器

      • 📋 概览
      • 📖 完整指南
    • 📦 MCP 服务器构建器

      • 📋 概览
      • 📖 完整指南
    • 🧪 Web 应用测试工具

      • 📋 概览
      • 📖 完整指南
  • 🏢 企业与沟通

    • 🎨 品牌指南

      • 📋 概览
      • 📖 完整指南
    • 📢 企业内部沟通

      • 📋 概览
      • 📖 完整指南
    • 💎 前端设计

      • 📋 概览
      • 📖 完整指南
  • 📄 文档处理

    • 📘 Word 文档处理

      • 📋 概览
      • 📖 完整指南
    • 📕 PDF 文档处理

      • 📋 概览
      • 📖 完整指南
    • 📙 PowerPoint 演示文稿处理

      • 📋 概览
      • 📖 完整指南
    • 📗 Excel 表格处理

      • 📋 概览
      • 📖 完整指南
  • 🔧 元技能

    • 🛠️ Skill 创建器

      • 📋 概览
      • 📖 完整指南
    • 📝 Skill 模板

      • 📋 概览
      • 📖 完整参考

Webapp Testing 完整指南

本文档包含使用 Playwright 测试 Web 应用的完整技术细节。如果您是初次接触,建议先阅读 📋 概览。

目录

  • 目录
  • 核心概念
    • Playwright 简介
    • 决策树
  • 辅助工具:with_server.py
    • 功能
    • 基本用法
    • 测试脚本
  • 侦察-行动模式
    • 完整流程
  • 选择器速查
    • 推荐优先级
    • 组合选择器
  • 等待策略
    • 网络空闲(动态应用必需)
    • 元素等待
    • 自定义条件
  • 截图和录屏
    • 截图
    • 录屏
  • 控制台日志捕获
  • 网络监控
    • 监听请求/响应
    • 拦截和修改
  • 常见陷阱
    • ❌ 陷阱 1:忘记等待
    • ❌ 陷阱 2:脆弱选择器
    • ❌ 陷阱 3:异步操作
  • 调试技巧
    • 交互式调试
    • 慢动作模式
    • 详细日志
  • 完整示例
    • 示例 1:登录流程测试
    • 示例 2:表单验证测试
    • 示例 3:购物流程测试
  • 参考资源
    • 官方文档
    • 示例文件
    • 辅助脚本

核心概念

Playwright 简介

Playwright 是微软开发的现代浏览器自动化工具:

  • ✅ 跨浏览器:Chromium、Firefox、WebKit
  • ✅ 速度快:比 Selenium 快 2-3 倍
  • ✅ 自动等待:智能等待元素出现
  • ✅ 功能丰富:截图、录屏、网络监控

决策树

用户任务
  │
  ▼
静态 HTML?
  ├─ 是 → 直接读取 HTML → 编写脚本 → file:// URL
  └─ 否 → 动态应用
           │
           ▼
         服务器已运行?
           ├─ 否 → with_server.py 启动
           └─ 是 → 侦察-行动模式

辅助工具:with_server.py

功能

自动管理服务器生命周期:启动 → 等待就绪 → 运行测试 → 清理

基本用法

# 单服务器
python scripts/with_server.py \
  --server "npm run dev" \
  --port 5173 \
  -- python test_app.py

# 多服务器(前后端)
python scripts/with_server.py \
  --server "cd backend && python app.py" --port 3000 \
  --server "cd frontend && npm run dev" --port 5173 \
  -- python test_fullstack.py

测试脚本

# test_app.py - 无需管理服务器
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    # 服务器已就绪
    page.goto('http://localhost:5173')
    page.wait_for_load_state('networkidle')
    
    page.click('button:has-text("登录")')
    browser.close()

侦察-行动模式

完整流程

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    # 1. 导航
    page.goto('http://localhost:5173')
    page.wait_for_load_state('networkidle')  # 关键!
    
    # 2. 侦察:截图
    page.screenshot(path='/tmp/inspect.png', full_page=True)
    
    # 3. 侦察:发现元素
    buttons = page.locator('button').all()
    for btn in buttons:
        print(f"发现按钮: {btn.text_content()}")
    
    # 4. 行动:使用发现的选择器
    page.click('button:has-text("提交")')
    page.wait_for_selector('text=提交成功')
    
    browser.close()

选择器速查

推荐优先级

# 1. 角色选择器(最佳)
page.click('role=button[name="提交"]')
page.fill('role=textbox[name="用户名"]', 'admin')

# 2. 文本选择器
page.click('text=登录')
page.click('button:has-text("确认")')

# 3. ID/CSS 选择器
page.click('#submit-button')
page.fill('input[name="email"]', 'test@example.com')

# 4. XPath(最后选择)
page.click('//button[contains(text(), "提交")]')

组合选择器

# CSS >> 文本
page.click('form >> text=登录')

# 多级选择
page.click('main >> section >> button:has-text("确认")')

等待策略

网络空闲(动态应用必需)

page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle')  # 等待 JS 执行

元素等待

# 等待出现
page.wait_for_selector('#success-message', timeout=5000)

# 等待消失
page.wait_for_selector('#loading', state='hidden')

# 等待可点击
page.wait_for_selector('button:not([disabled])')

自定义条件

# JavaScript 条件
page.wait_for_function('() => document.querySelector("#data").innerText !== "Loading..."')

# URL 等待
page.wait_for_url('**/dashboard')

截图和录屏

截图

# 全页截图
page.screenshot(path='screenshot.png', full_page=True)

# 元素截图
page.locator('#chart').screenshot(path='chart.png')

# 指定质量
page.screenshot(path='screenshot.jpg', type='jpeg', quality=80)

录屏

context = browser.new_context(
    record_video_dir='./videos',
    record_video_size={'width': 1280, 'height': 720}
)
page = context.new_page()

# 执行测试...

context.close()  # 视频自动保存

控制台日志捕获

console_messages = []

page.on('console', lambda msg: console_messages.append({
    'type': msg.type,
    'text': msg.text
}))

page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle')

# 执行操作...

# 分析日志
errors = [m for m in console_messages if m['type'] == 'error']
if errors:
    print(f"发现 {len(errors)} 个错误")
    for err in errors:
        print(f"  - {err['text']}")

网络监控

监听请求/响应

# 监听请求
page.on('request', lambda req: print(f"→ {req.method} {req.url}"))

# 监听响应
page.on('response', lambda res: print(f"← {res.status} {res.url}"))

# 过滤 API 请求
def log_api(request):
    if '/api/' in request.url:
        print(f"API: {request.method} {request.url}")

page.on('request', log_api)

拦截和修改

# 拦截特定请求
page.route('**/api/data', lambda route: route.fulfill(
    status=200,
    body='{"mocked": true}'
))

# 阻止资源加载
page.route('**/*.{png,jpg,jpeg}', lambda route: route.abort())

常见陷阱

❌ 陷阱 1:忘记等待

# 错误
page.goto('http://localhost:5173')
page.click('button')  # 失败:元素不存在

# 正确
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle')
page.click('button')

❌ 陷阱 2:脆弱选择器

# 错误:依赖 DOM 结构
page.click('div > div > button:nth-child(3)')

# 正确:语义化选择器
page.click('button:has-text("提交")')
page.click('role=button[name="提交"]')

❌ 陷阱 3:异步操作

# 错误:立即检查结果
page.click('button#load-data')
data = page.locator('#data').text_content()

# 正确:等待加载完成
page.click('button#load-data')
page.wait_for_selector('#data:not(:has-text("Loading..."))')
data = page.locator('#data').text_content()

调试技巧

交互式调试

browser = p.chromium.launch(headless=False)  # 可视模式
page = browser.new_page()
page.goto('http://localhost:5173')

page.pause()  # 暂停,打开调试器

慢动作模式

browser = p.chromium.launch(
    headless=False,
    slow_mo=1000  # 每步延迟 1 秒
)

详细日志

DEBUG=pw:api python test.py

完整示例

示例 1:登录流程测试

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    # 1. 访问登录页
    page.goto('http://localhost:5173')
    page.wait_for_load_state('networkidle')
    
    # 2. 填写表单
    page.fill('input[name="username"]', 'admin')
    page.fill('input[name="password"]', 'password123')
    
    # 3. 提交
    page.click('button:has-text("登录")')
    
    # 4. 验证成功
    page.wait_for_selector('text=欢迎')
    assert '欢迎' in page.content()
    
    print("✅ 登录测试通过")
    browser.close()

示例 2:表单验证测试

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    page.goto('http://localhost:5173/register')
    page.wait_for_load_state('networkidle')
    
    # 测试空表单提交
    page.click('button[type="submit"]')
    error = page.locator('.error-message').text_content()
    assert '请填写必填项' in error
    
    # 测试邮箱格式
    page.fill('input[name="email"]', 'invalid-email')
    page.click('button[type="submit"]')
    error = page.locator('.error-message').text_content()
    assert '邮箱格式不正确' in error
    
    print("✅ 表单验证测试通过")
    browser.close()

示例 3:购物流程测试

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    # 登录
    page.goto('http://localhost:5173/login')
    page.wait_for_load_state('networkidle')
    page.fill('input[name="username"]', 'customer')
    page.fill('input[name="password"]', 'password')
    page.click('button:has-text("登录")')
    
    # 浏览商品
    page.wait_for_url('**/dashboard')
    page.click('a:has-text("商品列表")')
    
    # 添加到购物车
    page.click('button.add-to-cart:nth-of-type(1)')
    page.wait_for_selector('text=已添加到购物车')
    
    # 结算
    page.click('a:has-text("购物车")')
    page.click('button:has-text("结算")')
    
    # 验证订单
    page.wait_for_selector('text=订单创建成功')
    order_number = page.locator('#order-number').text_content()
    print(f"✅ 订单创建成功: {order_number}")
    
    browser.close()

参考资源

官方文档

  • Playwright Python: https://playwright.dev/python/
  • API 参考: https://playwright.dev/python/docs/api/class-playwright
  • 选择器: https://playwright.dev/python/docs/selectors

示例文件

原始技能包含以下示例(位于 examples/ 目录):

  • element_discovery.py - 元素发现示例
  • static_html_automation.py - 静态 HTML 测试
  • console_logging.py - 控制台日志捕获

辅助脚本

  • scripts/with_server.py - 服务器生命周期管理

提示

始终先运行 --help 了解脚本用法,避免阅读源码污染上下文。


返回:📋 概览 | 技能列表

Prev
📋 概览