Webapp Testing Skill 详解
使用 Playwright 测试本地 Web 应用
基本信息
| 属性 | 值 |
|---|---|
| 名称 | webapp-testing |
| 类别 | 开发工具 |
| 输出格式 | 测试结果 / 截图 |
| 许可证 | Apache 2.0 |
yaml
name: webapp-testing
description: Toolkit for interacting with and testing local web applications
using Playwright. Supports verifying frontend functionality, debugging UI
behavior, capturing browser screenshots, and viewing browser logs.1. 核心概念
1.1 Playwright 简介
通俗比喻:Playwright 就像一个"机器人浏览器操作员"——它可以自动化打开网页、点击按钮、填写表单、截图等操作,就像真人在操作浏览器一样。
1.2 辅助脚本
markdown
**可用脚本**:
- `scripts/with_server.py` - 管理服务器生命周期(支持多服务器)
**重要**:始终先运行脚本的 --help 查看用法
不要先读取源码——这些脚本是作为黑盒工具使用的2. 决策树
mermaid
graph TD
A[用户任务] --> B{是静态 HTML?}
B -->|是| C[直接读取 HTML 识别选择器]
B -->|否| D{服务器已运行?}
C --> C1[成功] --> C2[使用选择器编写 Playwright 脚本]
C --> C3[失败/不完整] --> D
D -->|否| E[运行 with_server.py --help]
D -->|是| F[侦察后操作模式]
E --> E1[使用辅助脚本 + 简化 Playwright 脚本]
F --> F1[导航并等待 networkidle]
F1 --> F2[截图或检查 DOM]
F2 --> F3[从渲染状态识别选择器]
F3 --> F4[使用发现的选择器执行操作]3. 使用 with_server.py
3.1 查看帮助
bash
python scripts/with_server.py --help3.2 单服务器
bash
python scripts/with_server.py \
--server "npm run dev" \
--port 5173 \
-- python your_automation.py3.3 多服务器(后端 + 前端)
bash
python scripts/with_server.py \
--server "cd backend && python server.py" --port 3000 \
--server "cd frontend && npm run dev" --port 5173 \
-- python your_automation.py4. Playwright 脚本编写
4.1 基本模板
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # 始终使用 headless 模式
page = browser.new_page()
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle') # 关键:等待 JS 执行完成
# ... 你的自动化逻辑
browser.close()4.2 关键注意事项
markdown
**常见陷阱**:
❌ 不要在动态应用上等待 networkidle 之前检查 DOM
✅ 始终先等待 page.wait_for_load_state('networkidle')5. 侦察后操作模式
5.1 步骤1:检查渲染的 DOM
python
# 截图
page.screenshot(path='/tmp/inspect.png', full_page=True)
# 获取页面内容
content = page.content()
# 查找所有按钮
buttons = page.locator('button').all()5.2 步骤2:从检查结果识别选择器
分析截图或 DOM 内容,确定正确的选择器。
5.3 步骤3:使用发现的选择器执行操作
python
# 使用识别的选择器执行操作
page.locator('button:has-text("Submit")').click()
page.locator('#email').fill('test@example.com')6. 常用操作
6.1 元素交互
python
# 点击
page.locator('button').click()
page.locator('text=Submit').click()
# 填写表单
page.locator('#username').fill('user123')
page.locator('input[type="password"]').fill('secret')
# 选择下拉选项
page.locator('select#country').select_option('china')
# 复选框
page.locator('input[type="checkbox"]').check()
page.locator('input[type="checkbox"]').uncheck()6.2 等待操作
python
# 等待特定元素
page.wait_for_selector('.loading-complete')
# 等待固定时间(不推荐,仅用于调试)
page.wait_for_timeout(1000) # 1 秒
# 等待页面状态
page.wait_for_load_state('networkidle')
page.wait_for_load_state('domcontentloaded')6.3 截图和调试
python
# 截图
page.screenshot(path='screenshot.png')
page.screenshot(path='full.png', full_page=True)
# 获取元素截图
page.locator('.header').screenshot(path='header.png')7. 选择器类型
7.1 推荐的选择器
python
# 文本内容
page.locator('text=Click me')
page.locator(':has-text("Welcome")')
# 角色
page.locator('role=button')
page.locator('role=textbox')
# CSS 选择器
page.locator('.class-name')
page.locator('#element-id')
page.locator('button.primary')
# 组合选择器
page.locator('form >> input[type="email"]')7.2 最佳实践
markdown
- 使用描述性选择器:`text=`, `role=`, CSS 选择器, 或 ID
- 添加适当的等待:`page.wait_for_selector()` 或超时8. 示例脚本
8.1 元素发现
python
# examples/element_discovery.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')
# 发现按钮
buttons = page.locator('button').all()
for btn in buttons:
print(f"Button: {btn.text_content()}")
# 发现链接
links = page.locator('a').all()
for link in links:
print(f"Link: {link.get_attribute('href')}")
# 发现输入框
inputs = page.locator('input').all()
for inp in inputs:
print(f"Input: {inp.get_attribute('name')}")
browser.close()8.2 静态 HTML 自动化
python
# examples/static_html_automation.py
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 使用 file:// URL 加载本地 HTML
page.goto('file:///path/to/local/index.html')
# 执行操作
page.locator('button#submit').click()
browser.close()8.3 控制台日志捕获
python
# examples/console_logging.py
from playwright.sync_api import sync_playwright
def handle_console(msg):
print(f"Console {msg.type}: {msg.text}")
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 监听控制台消息
page.on('console', handle_console)
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle')
# 执行可能产生日志的操作
page.locator('button').click()
browser.close()9. 最佳实践
9.1 使用打包脚本作为黑盒
markdown
**重要**:
- 考虑 scripts/ 中的脚本是否能完成任务
- 使用 --help 查看用法
- 直接调用,而非读取源码到上下文
- 这些脚本处理常见的复杂工作流9.2 脚本编写规范
markdown
- 使用 sync_playwright() 进行同步脚本
- 始终关闭浏览器
- 使用描述性选择器
- 添加适当的等待10. 使用示例
10.1 触发方式
"帮我测试这个 Web 应用的登录功能"
"截取这个页面的截图"
"test the form submission on localhost:3000"
"debug why the button click doesn't work"10.2 典型场景
| 场景 | 方法 |
|---|---|
| 测试静态 HTML | 直接读取 HTML,编写选择器 |
| 测试运行中的服务器 | 侦察后操作模式 |
| 测试需要启动的服务器 | with_server.py + 自动化脚本 |
| 调试 UI 行为 | 截图 + 控制台日志捕获 |
11. 本节小结
| 要点 | 说明 |
|---|---|
| 核心工具 | Playwright + with_server.py |
| 关键等待 | 始终等待 networkidle |
| 侦察模式 | 先检查 DOM,再执行操作 |
| 选择器 | 使用 text=, role=, CSS, ID |
| 最佳实践 | 脚本作为黑盒使用 |
返回:Skills 目录