# 执行准确率差异分析：`pc自动化测试` vs `platform-auto-test`

## 核心结论

**`pc自动化测试` 准确率远高于 `platform-auto-test`，根本原因不是框架本身的差异，而是"选择器质量"和"等待策略"两个维度的差距。**

---

## 差异一：选择器的精确度（最关键差异）

### `pc自动化测试` — 精确到具体组件的 CSS class

Page Object 中使用**从 Vue 组件源码直接确定的、多级嵌套的具体 class**：

```javascript
// Step1Page.js — 选择器非常具体
get meetingNameInput() {
  return this.page.locator('.bookv3-slim-form .field-name input[placeholder="请输入"]').first();
}

get roomInput() {
  return this.page.locator('.bookv3-slim-form .field-room .room-input');
}

get nextButton() {
  return this.page.locator('.footer-next-btn-v3');
}
```

**特点**：
- 选择器由**人写代码时直接从组件 DOM 结构确定**
- 多层嵌套（form > field > input），唯一性极高
- 使用 `placeholder`、`class` 等稳定属性组合定位

### `platform-auto-test` — 通用选择器，录制器自动生成

```python
# playwright_executor.py — 自动登录时的选择器
inputs = self._page.query_selector_all('input:visible')
for inp in inputs:
    ph = inp.get_attribute('placeholder') or ''
    if '手机' in ph or '用户' in ph or '邮箱' in ph or 'account' in ph.lower():
        inp.fill(self.LOGIN_CONFIG["username"])
```

**特点**：
- 选择器存在数据库的步骤 params 中，由**录制器自动生成**
- 录制器生成的选择器通常是单层 class（如 `.el-input`、`button`）
- 自动生成的选择器缺乏上下文，容易匹配到多个元素
- 录制器捕获时的 DOM 结构与执行时的 DOM 结构可能有差异

### 对比

| 维度 | pc自动化测试 | platform-auto-test |
|------|-------------|-------------------|
| 选择器来源 | 开发人员手写 | 录制器自动生成 |
| 选择器粒度 | 多级嵌套，精确到具体字段 | 单层/通用 |
| 唯一性 | 高 — 一个选择器对应一个元素 | 低 — 易匹配到多个 |
| 稳定性 | 高 — 针对组件结构设计 | 中 — 依赖录制时 DOM |
| 抗页面变化 | 中 — class 变化会断 | 低 — 通用选择器更容易误点 |

---

## 差异二：等待策略

### `pc自动化测试` — 显式等待 + 固定延时 + 容错

```javascript
// 1. 明确等待元素可见
await this.meetingNameInput.waitFor({ state: 'visible' });

// 2. 固定延时确保弹窗动画完成
await this.page.waitForTimeout(800);

// 3. 多重容错：多种方式尝试
if (await emptyBtn.first().isVisible().catch(() => false)) {
  // 方式A
} else if (await addSquare.first().isVisible().catch(() => false)) {
  // 方式B
}
```

### `platform-auto-test` — 简单等待 + 静默失败

```python
def _do_click(self, params: dict) -> None:
    selector = params.get("selector", "")
    # 等待10秒，失败则直接忽略
    try:
        self._page.wait_for_selector(selector, state="visible", timeout=10000)
    except Exception:
        pass  # ← 静默忽略，继续尝试点击

    # 尝试点击，失败则静默忽略
    try:
        self._page.click(selector, timeout=5000)
        return
    except Exception:
        pass  # ← 静默忽略

    # iframe fallback
    for frame in self._page.frames:
        ...
```

**问题**：静默太多，步骤报告显示 "passed" 但实际上可能根本没点到正确元素。

### 对比

| 等待策略 | pc自动化测试 | platform-auto-test |
|---------|-------------|-------------------|
| 元素可见等待 | ✅ 明确 waitFor({state:'visible'}) | ⚠️ 等待超时后静默继续 |
| 弹窗/动画等待 | ✅ 固定延时 500-800ms | ❌ 无 |
| 操作间间隔 | ✅ 每步间有 waitForTimeout | ❌ 连续执行 |
| 失败反馈 | ❌ throw error（测试直接 fail） | ⚠️ 静默 pass，但操作无效 |

---

## 差异三：操作交互的健壮性

### `pc自动化测试` 的做法

```javascript
// 清空输入框：先 triple-click 全选 → Ctrl+A → Delete → fill
await this.meetingNameInput.click({ clickCount: 3, force: true });
await this.page.keyboard.press('Control+A');
await this.page.keyboard.press('Delete');
await this.meetingNameInput.fill(name);

// 点击被覆盖的元素：force: true 绕过覆盖层
await moreBtn.click({ force: true });

// 多选器回退：一个选择器不行就换一个
var confirmBtn = dialogContainer.locator('button').filter({ hasText: /^确定$/ }).first();
if (!btnVisible) {
  confirmBtn = dialogContainer.locator('.el-dialog__footer button, .el-message-box__btns button')
    .filter({ hasText: '确定' }).first();
}
```

### `platform-auto-test` 的做法

```python
# 简单的 fill
self._page.fill(selector, str(value))

# 简单的 click
self._page.click(selector, timeout=5000)
```

### 关键差别

| 操作 | pc自动化测试 | platform-auto-test |
|------|-------------|-------------------|
| 输入框清空 | triple-click + Ctrl+A + Delete + fill | 直接 fill（不清空已有内容） |
| 覆盖层点击 | `force: true` 绕过 | 无 force，被覆盖时失败 |
| 多选器回退 | 2-3 种选择器依次尝试 | 无回退 |
| 按钮匹配 | `filter({hasText})` 文本匹配 | 无 |

---

## 差异四：浏览器配置

```javascript
// pc自动化测试 — 使用系统已安装的 Chrome
channel: 'chrome',
launchOptions: {
  args: [
    '--start-maximized',
    '--window-size=1920,1080',
    '--disable-infobars',
  ],
},
```

```python
# platform-auto-test — 使用 Playwright 内置 Chromium
self._browser = self._playwright.chromium.launch(
    headless=self.headless,
    args=["--no-sandbox", "--disable-setuid-sandbox"],
)
```

**差异**：系统 Chrome 更接近用户真实环境，内置 Chromium 的行为可能与真实环境有偏差。`--no-sandbox` 模式在某些场景下会导致 CSS 渲染差异。

---

## 差异五：日志和调试能力

```javascript
// pc自动化测试 — 每步都有详细日志
console.log(`  ✓ 已填写会议名称: ${name}`);
console.log(`  ✓ 已打开会议室选择弹窗`);
console.log(`  ✓ 已点击"下一步"`);
```

```python
# platform-auto-test — 缺乏细粒度执行日志
logger.debug(f"填充输入框: {params.get('selector', '')} = {params.get('value', '')}")
```

**问题**：`platform-auto-test` 的日志级别是 `debug`，在默认配置下**看不到**。即使步骤失败了，也只能看到 "failed" 状态，不知道具体卡在哪一步的哪个选择器。

---

## 差异六：测试用例的设计粒度

| 维度 | pc自动化测试 | platform-auto-test |
|------|-------------|-------------------|
| 用例粒度 | **业务场景级**（51 个完整工作流） | **页面访问级**（26 个基本验证） |
| 单用例步骤数 | 10-30+ 步（全流程） | 3 步（导航 + 等待 + 截图） |
| 复杂交互 | 多步表单填写、弹窗交互、下拉菜单 | 基本页面访问 |
| 数据清理 | 自动取消会议，不留脏数据 | 无 |

`pc自动化测试` 的用例更"深"——每个用例经过多次"创建→验证→编辑→验证"的循环，每一步都验证了上一步确实生效。而 `platform-auto-test` 的用例更"浅"——大多是"访问页面 → 等待 → 截图"，即使有操作也是单步的，无法形成验证闭环。

---

## 根因总结

| 根因 | 影响程度 | 说明 |
|------|---------|------|
| **选择器质量** | ★★★★★ | pc 的手写选择器 vs 平台的录制自动生成，这是最大差距 |
| **等待策略** | ★★★★☆ | pc 有显式等待 + 固定延时 + 容错，平台过于简陋 |
| **交互健壮性** | ★★★★☆ | pc 有 force click、多选器回退、文本匹配，平台没有 |
| **用例深度** | ★★★☆☆ | pc 的用例步骤多、形成验证闭环，平台的用例太浅 |
| **浏览器配置** | ★★☆☆☆ | 系统 Chrome vs 内置 Chromium，影响较小 |
| **日志调试** | ★★☆☆☆ | pc 能看到每步详细输出，平台日志不直观 |

---

## 改进建议

### 短期（可快速落地）

1. **选择器优化**：改进录制器，生成带上下文的多级选择器（如 `.bookv3-slim-form .field-name input`），而非单层 class
2. **增加等待延时**：每个关键操作后加 300-800ms 等待，给页面动画留时间
3. **添加 force click**：对 click 操作增加 `force=True` 参数，绕过覆盖层
4. **优化日志**：将关键操作日志从 debug 改为 info，让用户在界面上能看到每步执行情况

### 中期

5. **引入多选器回退机制**：每个步骤存 2-3 个备选选择器，主选择器失败时自动回退
6. **改进录制器**：录制时不仅捕获 class，还捕获 `placeholder`、`aria-label`、`text` 等稳定属性
7. **丰富用例深度**：将现有的 26 个浅用例扩展为包含"操作+验证"的完整业务流程

### 长期

8. **引入视觉定位**：使用 AI/Screenshot 比对来定位元素，而非完全依赖 DOM 选择器
9. **自动愈合 (Self-Healing)**：当选择器失效时，自动分析 DOM 差异并修复选择器

---

## 一句话总结

**不是平台本身不准，而是"手写测试代码"天然比"录制器自动生成"更精准**——人写代码时知道要点击哪个具体的按钮，而录制器只能记录"点击了第 3 个 `.el-button`"，后者的容错空间小得多。改进录制器的选择器生成策略，是拉平差距的最有效手段。