# UI 集成测试指南 ## 📋 概述 UI 集成测试使用 **Playwright** 框架来测试正则路径替换功能的用户界面交互。 ## 🚀 快速开始 ### 1. 安装依赖 ```bash # 安装 Playwright 和浏览器驱动 pip install pytest-playwright playwright install chromium # 或安装所有浏览器 playwright install ``` ### 2. 启动应用服务器 在运行 UI 测试前,需要先启动应用: ```bash # 方式 1: 直接运行 uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 # 方式 2: 使用 Docker docker compose up ``` ### 3. 运行 UI 测试 ```bash # 无头模式(不显示浏览器) 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: 添加单个规则 ```python # 1. 点击"添加规则"按钮 # 2. 填写正则表达式: /old/path/ # 3. 填写替换文本: /new/path/ # 4. 验证输入框内容正确 ``` ### 场景 2: NAS 路径规范化 ```python # 添加三条规则: # 1. \\koha9-nas\koha9-nas\Music → N:\Music # 2. /music/cache/ → /data/music/ # 3. \ → / # # 保存并验证规则持久化 ``` ### 场景 3: 规则持久化验证 ```python # 1. 添加规则 # 2. 保存 # 3. 刷新页面 # 4. 验证规则仍然存在 ``` ## 🔧 配置选项 ### pytest.ini 配置 ```ini [pytest] # Playwright 配置 addopts = --browser=chromium --headed --slowmo=100 ``` ### 环境变量 ```bash # 设置测试服务器地址 export TEST_SERVER_URL="http://localhost:8000" # 设置浏览器类型 export BROWSER=chromium # 或 firefox, webkit ``` ## 🐛 调试技巧 ### 1. 使用有头模式 ```bash pytest tests/test_ui_regex_rules.py --headed ``` ### 2. 使用慢速模式 ```bash pytest tests/test_ui_regex_rules.py --headed --slowmo=1000 ``` ### 3. 截图调试 在测试中添加截图: ```python def test_something(page: Page): page.screenshot(path="debug_screenshot.png") ``` ### 4. 使用 Playwright Inspector ```bash # 启动调试模式 PWDEBUG=1 pytest tests/test_ui_regex_rules.py::test_add_single_rule ``` ### 5. 查看追踪 ```python # 在 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") ``` 然后查看: ```bash playwright show-trace trace.zip ``` ## 📝 编写新的 UI 测试 ### 基本模板 ```python 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") ``` ### 等待策略 ```python # 等待元素可见 page.wait_for_selector("#element", state="visible") # 等待网络空闲 page.wait_for_load_state("networkidle") # 等待特定时间(尽量避免) page.wait_for_timeout(1000) # 1 秒 ``` ### 选择器策略 ```python # 推荐: 使用 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 模式 ```python 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 清理状态 ```python @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. 避免硬编码等待时间 ```python # ❌ 不好 page.wait_for_timeout(2000) # ✅ 好 page.wait_for_selector("#element", state="visible") page.wait_for_load_state("networkidle") ``` ### 4. 使用断言而非 if 判断 ```python # ❌ 不好 assert page.locator("#element").count() > 0 # ✅ 好 expect(page.locator("#element")).to_be_visible() ``` ## 🔄 CI/CD 集成 ### GitHub Actions 示例 ```yaml 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/ ``` ## 📚 参考资料 - [Playwright 官方文档](https://playwright.dev/python/) - [pytest-playwright 插件](https://github.com/microsoft/playwright-pytest) - [Playwright 最佳实践](https://playwright.dev/python/docs/best-practices) ## 🆘 常见问题 ### 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()`,使用事件驱动的等待方法