7.6 KiB
7.6 KiB
UI 集成测试指南
📋 概述
UI 集成测试使用 Playwright 框架来测试正则路径替换功能的用户界面交互。
🚀 快速开始
1. 安装依赖
# 安装 Playwright 和浏览器驱动
pip install pytest-playwright
playwright install chromium
# 或安装所有浏览器
playwright install
2. 启动应用服务器
在运行 UI 测试前,需要先启动应用:
# 方式 1: 直接运行
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# 方式 2: 使用 Docker
docker compose up
3. 运行 UI 测试
# 无头模式(不显示浏览器)
pytest tests/test_ui_regex_rules.py -v
# 有头模式(显示浏览器,便于调试)
pytest tests/test_ui_regex_rules.py -v --headed
# 慢速模式(方便观察)
pytest tests/test_ui_regex_rules.py -v --headed --slowmo=500
# 运行特定测试
pytest tests/test_ui_regex_rules.py::TestRegexRulesUI::test_add_single_rule -v --headed
📊 测试覆盖
基础 UI 交互测试 (TestRegexRulesUI)
| 测试 | 描述 |
|---|---|
test_page_loads_successfully |
页面成功加载 |
test_add_single_rule |
添加单个规则 |
test_add_multiple_rules |
添加多个规则 |
test_remove_rule |
删除规则 |
test_save_rules |
保存规则 |
test_rules_persist_after_save |
规则持久化验证 |
test_empty_pattern_validation |
空模式验证 |
test_rule_order_preserved |
规则顺序保持 |
复杂场景测试 (TestComplexScenarios)
| 测试 | 描述 |
|---|---|
test_windows_to_linux_path_conversion |
Windows → Linux 路径转换 |
test_nas_path_normalization |
NAS 路径规范化 |
性能测试 (TestPerformance)
| 测试 | 描述 |
|---|---|
test_add_many_rules_performance |
添加大量规则性能 |
🎯 测试场景示例
场景 1: 添加单个规则
# 1. 点击"添加规则"按钮
# 2. 填写正则表达式: /old/path/
# 3. 填写替换文本: /new/path/
# 4. 验证输入框内容正确
场景 2: NAS 路径规范化
# 添加三条规则:
# 1. \\koha9-nas\koha9-nas\Music → N:\Music
# 2. /music/cache/ → /data/music/
# 3. \ → /
#
# 保存并验证规则持久化
场景 3: 规则持久化验证
# 1. 添加规则
# 2. 保存
# 3. 刷新页面
# 4. 验证规则仍然存在
🔧 配置选项
pytest.ini 配置
[pytest]
# Playwright 配置
addopts =
--browser=chromium
--headed
--slowmo=100
环境变量
# 设置测试服务器地址
export TEST_SERVER_URL="http://localhost:8000"
# 设置浏览器类型
export BROWSER=chromium # 或 firefox, webkit
🐛 调试技巧
1. 使用有头模式
pytest tests/test_ui_regex_rules.py --headed
2. 使用慢速模式
pytest tests/test_ui_regex_rules.py --headed --slowmo=1000
3. 截图调试
在测试中添加截图:
def test_something(page: Page):
page.screenshot(path="debug_screenshot.png")
4. 使用 Playwright Inspector
# 启动调试模式
PWDEBUG=1 pytest tests/test_ui_regex_rules.py::test_add_single_rule
5. 查看追踪
# 在 conftest.py 中添加
@pytest.fixture
def context(browser):
context = browser.new_context()
context.tracing.start(screenshots=True, snapshots=True)
yield context
context.tracing.stop(path="trace.zip")
然后查看:
playwright show-trace trace.zip
📝 编写新的 UI 测试
基本模板
def test_my_feature(page: Page):
"""测试我的功能"""
# 1. 导航到页面
page.goto("http://localhost:8000")
# 2. 与元素交互
button = page.locator("#myButton")
button.click()
# 3. 验证结果
expect(page.locator("#result")).to_have_text("Success")
等待策略
# 等待元素可见
page.wait_for_selector("#element", state="visible")
# 等待网络空闲
page.wait_for_load_state("networkidle")
# 等待特定时间(尽量避免)
page.wait_for_timeout(1000) # 1 秒
选择器策略
# 推荐: 使用 data-testid
page.locator("[data-testid='add-rule-btn']")
# 通过文本
page.locator("button:has-text('保存规则')")
# 通过 ID
page.locator("#addRuleBtn")
# 通过 CSS 类
page.locator(".rule-row")
# 组合选择器
page.locator(".rule-row input[name='pattern']")
🎨 最佳实践
1. 使用 Page Object 模式
class RulesPage:
def __init__(self, page: Page):
self.page = page
self.add_button = page.locator("#addRuleBtn")
self.save_button = page.locator("button:has-text('保存规则')")
def add_rule(self, pattern: str, replacement: str):
self.add_button.click()
self.page.wait_for_timeout(100)
patterns = self.page.locator("input[name='pattern']")
replacements = self.page.locator("input[name='replacement']")
patterns.last.fill(pattern)
replacements.last.fill(replacement)
def save(self):
self.save_button.click()
self.page.wait_for_load_state("networkidle")
# 使用
def test_with_page_object(page: Page):
rules_page = RulesPage(page)
rules_page.add_rule(r"/old/", r"/new/")
rules_page.save()
2. 使用 Fixtures 清理状态
@pytest.fixture
def clean_rules(page: Page):
"""清除所有规则"""
page.goto("http://localhost:8000")
while page.locator(".rule-row").count() > 0:
page.locator(".rule-row button[title='删除此规则']").first.click()
page.wait_for_timeout(50)
yield
3. 避免硬编码等待时间
# ❌ 不好
page.wait_for_timeout(2000)
# ✅ 好
page.wait_for_selector("#element", state="visible")
page.wait_for_load_state("networkidle")
4. 使用断言而非 if 判断
# ❌ 不好
assert page.locator("#element").count() > 0
# ✅ 好
expect(page.locator("#element")).to_be_visible()
🔄 CI/CD 集成
GitHub Actions 示例
name: UI Tests
on: [push, pull_request]
jobs:
ui-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pytest-playwright
playwright install --with-deps chromium
- name: Start application
run: |
uvicorn app.main:app --host 0.0.0.0 --port 8000 &
sleep 5
- name: Run UI tests
run: pytest tests/test_ui_regex_rules.py -v
- name: Upload screenshots on failure
if: failure()
uses: actions/upload-artifact@v2
with:
name: screenshots
path: screenshots/
📚 参考资料
🆘 常见问题
Q: 测试运行时找不到浏览器?
A: 运行 playwright install chromium
Q: 测试失败,如何调试?
A: 使用 --headed --slowmo=500 参数可视化执行过程
Q: 如何在测试中等待异步操作?
A: 使用 page.wait_for_load_state("networkidle") 或 page.wait_for_selector()
Q: 如何处理动态加载的内容?
A: 使用 expect().to_be_visible() 会自动等待元素出现
Q: 测试很慢怎么办?
A: 减少不必要的 wait_for_timeout(),使用事件驱动的等待方法