# E2E测试优化实现计划

> **面向 AI 代理的工作者：** 必需子技能：使用 superpowers:subagent-driven-development（推荐）或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框（`- [ ]`）语法来跟踪进度。

**目标：** 将E2E测试通过率从17.3%提升至100%，并优化测试执行时间至12分钟以内

**架构：** 采用分阶段实施策略，第一阶段修复基础导航问题（目标50%通过率），第二阶段精准化选择器（目标90%通过率），第三阶段优化性能（目标100%通过率）

**技术栈：** Playwright, TypeScript, Vue 3, Element Plus

---

## 文件结构

### 将要修改的文件

**Page Object类**（优化导航和选择器）：
- `novalon-manage-web/e2e/pages/UserManagementPage.ts` - 用户管理页面
- `novalon-manage-web/e2e/pages/RoleManagementPage.ts` - 角色管理页面
- `novalon-manage-web/e2e/pages/MenuManagementPage.ts` - 菜单管理页面
- `novalon-manage-web/e2e/pages/SystemConfigPage.ts` - 系统配置页面
- `novalon-manage-web/e2e/pages/DictionaryManagementPage.ts` - 字典管理页面
- `novalon-manage-web/e2e/pages/FileManagementPage.ts` - 文件管理页面
- `novalon-manage-web/e2e/pages/OperationLogPage.ts` - 操作日志页面
- `novalon-manage-web/e2e/pages/LoginLogPage.ts` - 登录日志页面
- `novalon-manage-web/e2e/pages/ExceptionLogPage.ts` - 异常日志页面

**测试配置文件**（优化性能）：
- `novalon-manage-web/e2e/global-setup.ts` - 全局setup优化
- `novalon-manage-web/playwright.config.ts` - 测试配置优化

**测试用例文件**（修复选择器）：
- `novalon-manage-web/e2e/system-integration-test.spec.ts` - 系统集成测试

---

## 第一阶段：基础导航修复

**目标：** 测试通过率提升至50%以上（至少26个测试用例通过）

---

### 任务 1：验证页面存在性

**文件：**
- 修改：`novalon-manage-web/src/router/index.ts`（验证路由配置）

- [ ] **步骤 1：检查路由配置文件**

读取路由配置文件，确认所有测试用例涉及的页面都已配置：

```bash
cat novalon-manage-web/src/router/index.ts
```

预期：看到所有路由配置（/users, /roles, /menus, /sys/config, /dict, /files, /loginlog, /oplog, /exceptionlog）

- [ ] **步骤 2：验证页面组件是否存在**

检查每个路由对应的Vue组件是否存在：

```bash
ls -la novalon-manage-web/src/views/system/
ls -la novalon-manage-web/src/views/config/
ls -la novalon-manage-web/src/views/file/
ls -la novalon-manage-web/src/views/audit/
```

预期：所有组件文件都存在

- [ ] **步骤 3：记录缺失的页面**

如果发现缺失的页面，记录下来：

```markdown
# 缺失页面列表
- 无（所有页面都已实现）
```

---

### 任务 2：优化UserManagementPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/UserManagementPage.ts`

- [ ] **步骤 1：读取当前UserManagementPage代码**

```bash
cat novalon-manage-web/e2e/pages/UserManagementPage.ts
```

- [ ] **步骤 2：优化goto方法**

修改`goto`方法，添加更健壮的导航逻辑：

```typescript
async goto() {
  try {
    console.log('导航到用户管理页面...');
    await this.page.goto('/users');
    
    // 等待页面加载完成
    await this.page.waitForLoadState('networkidle');
    
    // 等待关键元素出现
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    
    // 验证页面URL
    await expect(this.page).toHaveURL(/.*users/);
    
    console.log('用户管理页面加载完成');
  } catch (error) {
    // 截图保存错误状态
    await this.page.screenshot({ path: `test-results/user-management-error-${Date.now()}.png` });
    
    // 记录错误信息
    console.error('导航到用户管理页面失败:', error);
    
    // 抛出更详细的错误信息
    throw new Error(`导航到用户管理页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：添加waitForTableReady方法**

添加智能等待表格加载的方法：

```typescript
async waitForTableReady() {
  // 等待表格出现
  await this.table.waitFor({ state: 'visible', timeout: 10000 });
  
  // 等待表格数据加载完成（至少有一行数据）
  await this.page.waitForFunction(
    () => {
      const rows = document.querySelectorAll('.el-table__body-wrapper tbody tr');
      return rows.length > 0;
    },
    { timeout: 5000 }
  ).catch(() => {
    // 如果没有数据，也继续执行（可能是空表格）
    console.log('表格没有数据，继续执行');
  });
}
```

- [ ] **步骤 4：提交修改**

```bash
git add novalon-manage-web/e2e/pages/UserManagementPage.ts
git commit -m "fix: optimize UserManagementPage navigation with better error handling"
```

---

### 任务 3：优化RoleManagementPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/RoleManagementPage.ts`

- [ ] **步骤 1：读取当前RoleManagementPage代码**

```bash
cat novalon-manage-web/e2e/pages/RoleManagementPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到角色管理页面...');
    await this.page.goto('/roles');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*roles/);
    
    console.log('角色管理页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/role-management-error-${Date.now()}.png` });
    console.error('导航到角色管理页面失败:', error);
    throw new Error(`导航到角色管理页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：添加waitForTableReady方法**

```typescript
async waitForTableReady() {
  await this.table.waitFor({ state: 'visible', timeout: 10000 });
  
  await this.page.waitForFunction(
    () => {
      const rows = document.querySelectorAll('.el-table__body-wrapper tbody tr');
      return rows.length > 0;
    },
    { timeout: 5000 }
  ).catch(() => {
    console.log('表格没有数据，继续执行');
  });
}
```

- [ ] **步骤 4：提交修改**

```bash
git add novalon-manage-web/e2e/pages/RoleManagementPage.ts
git commit -m "fix: optimize RoleManagementPage navigation with better error handling"
```

---

### 任务 4：优化MenuManagementPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/MenuManagementPage.ts`

- [ ] **步骤 1：读取当前MenuManagementPage代码**

```bash
cat novalon-manage-web/e2e/pages/MenuManagementPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到菜单管理页面...');
    await this.page.goto('/menus');
    
    await this.page.waitForLoadState('networkidle');
    
    // 菜单管理页面可能是树形结构，等待树形组件
    await this.page.waitForSelector('.el-tree', { timeout: 10000 }).catch(() => {
      // 如果没有树形组件，等待表格
      return this.page.waitForSelector('.el-table', { timeout: 5000 });
    });
    
    await expect(this.page).toHaveURL(/.*menus/);
    
    console.log('菜单管理页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/menu-management-error-${Date.now()}.png` });
    console.error('导航到菜单管理页面失败:', error);
    throw new Error(`导航到菜单管理页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/MenuManagementPage.ts
git commit -m "fix: optimize MenuManagementPage navigation with better error handling"
```

---

### 任务 5：优化SystemConfigPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/SystemConfigPage.ts`

- [ ] **步骤 1：读取当前SystemConfigPage代码**

```bash
cat novalon-manage-web/e2e/pages/SystemConfigPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到系统配置页面...');
    await this.page.goto('/sys/config');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*config/);
    
    console.log('系统配置页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/system-config-error-${Date.now()}.png` });
    console.error('导航到系统配置页面失败:', error);
    throw new Error(`导航到系统配置页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/SystemConfigPage.ts
git commit -m "fix: optimize SystemConfigPage navigation with better error handling"
```

---

### 任务 6：优化DictionaryManagementPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/DictionaryManagementPage.ts`

- [ ] **步骤 1：读取当前DictionaryManagementPage代码**

```bash
cat novalon-manage-web/e2e/pages/DictionaryManagementPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到字典管理页面...');
    await this.page.goto('/dict');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*dict/);
    
    console.log('字典管理页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/dict-management-error-${Date.now()}.png` });
    console.error('导航到字典管理页面失败:', error);
    throw new Error(`导航到字典管理页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/DictionaryManagementPage.ts
git commit -m "fix: optimize DictionaryManagementPage navigation with better error handling"
```

---

### 任务 7：优化FileManagementPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/FileManagementPage.ts`

- [ ] **步骤 1：读取当前FileManagementPage代码**

```bash
cat novalon-manage-web/e2e/pages/FileManagementPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到文件管理页面...');
    await this.page.goto('/files');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*files/);
    
    console.log('文件管理页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/file-management-error-${Date.now()}.png` });
    console.error('导航到文件管理页面失败:', error);
    throw new Error(`导航到文件管理页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/FileManagementPage.ts
git commit -m "fix: optimize FileManagementPage navigation with better error handling"
```

---

### 任务 8：优化OperationLogPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/OperationLogPage.ts`

- [ ] **步骤 1：读取当前OperationLogPage代码**

```bash
cat novalon-manage-web/e2e/pages/OperationLogPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到操作日志页面...');
    await this.page.goto('/oplog');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*oplog/);
    
    console.log('操作日志页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/operation-log-error-${Date.now()}.png` });
    console.error('导航到操作日志页面失败:', error);
    throw new Error(`导航到操作日志页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/OperationLogPage.ts
git commit -m "fix: optimize OperationLogPage navigation with better error handling"
```

---

### 任务 9：优化LoginLogPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/LoginLogPage.ts`

- [ ] **步骤 1：读取当前LoginLogPage代码**

```bash
cat novalon-manage-web/e2e/pages/LoginLogPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到登录日志页面...');
    await this.page.goto('/loginlog');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*loginlog/);
    
    console.log('登录日志页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/login-log-error-${Date.now()}.png` });
    console.error('导航到登录日志页面失败:', error);
    throw new Error(`导航到登录日志页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/LoginLogPage.ts
git commit -m "fix: optimize LoginLogPage navigation with better error handling"
```

---

### 任务 10：优化ExceptionLogPage导航

**文件：**
- 修改：`novalon-manage-web/e2e/pages/ExceptionLogPage.ts`

- [ ] **步骤 1：读取当前ExceptionLogPage代码**

```bash
cat novalon-manage-web/e2e/pages/ExceptionLogPage.ts
```

- [ ] **步骤 2：优化goto方法**

```typescript
async goto() {
  try {
    console.log('导航到异常日志页面...');
    await this.page.goto('/exceptionlog');
    
    await this.page.waitForLoadState('networkidle');
    await this.table.waitFor({ state: 'visible', timeout: 10000 });
    await expect(this.page).toHaveURL(/.*exceptionlog/);
    
    console.log('异常日志页面加载完成');
  } catch (error) {
    await this.page.screenshot({ path: `test-results/exception-log-error-${Date.now()}.png` });
    console.error('导航到异常日志页面失败:', error);
    throw new Error(`导航到异常日志页面失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/ExceptionLogPage.ts
git commit -m "fix: optimize ExceptionLogPage navigation with better error handling"
```

---

### 任务 11：运行第一阶段测试验证

**文件：**
- 无文件修改

- [ ] **步骤 1：运行完整测试套件**

```bash
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts --project=chromium --retries=0
```

预期：测试通过率提升至50%以上（至少26个测试用例通过）

- [ ] **步骤 2：收集测试结果**

查看测试报告：

```bash
cat test-results/results.json | jq '.suites[0].suites[0].suites[] | {title: .title, passed: [.specs[] | select(.ok == true)] | length, total: (.specs | length)}'
```

- [ ] **步骤 3：分析剩余失败原因**

记录第一阶段修复后的测试通过率和剩余失败原因：

```markdown
# 第一阶段测试结果
- 总测试数：52
- 通过数：[实际通过数]
- 失败数：[实际失败数]
- 通过率：[实际通过率]%

# 剩余失败原因分析
1. 选择器问题：[数量]个
2. 其他问题：[数量]个
```

---

## 第二阶段：选择器精准化

**目标：** 测试通过率提升至90%以上（至少47个测试用例通过）

---

### 任务 12：启用Playwright trace功能

**文件：**
- 修改：`novalon-manage-web/playwright.config.ts`

- [ ] **步骤 1：读取当前playwright配置**

```bash
cat novalon-manage-web/playwright.config.ts
```

- [ ] **步骤 2：启用trace功能**

在`use`配置中添加trace选项：

```typescript
use: {
  // ... 其他配置
  trace: 'on-first-retry',
  screenshot: 'only-on-failure',
  video: 'retain-on-failure',
}
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/playwright.config.ts
git commit -m "feat: enable Playwright trace for debugging"
```

---

### 任务 13：诊断失败测试的选择器问题

**文件：**
- 无文件修改

- [ ] **步骤 1：运行失败测试并生成trace**

选择一个失败的测试用例运行：

```bash
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts:104 --project=chromium --trace on
```

- [ ] **步骤 2：查看trace报告**

```bash
npx playwright show-trace test-results/[trace-file].zip
```

- [ ] **步骤 3：记录选择器问题**

根据trace报告，记录选择器问题：

```markdown
# 选择器问题列表
1. `.user-table` - 实际选择器应该是`.el-table`
2. `.user-row` - 实际选择器应该是`.el-table__body-wrapper tbody tr`
3. ...
```

---

### 任务 14：更新UserManagementPage选择器

**文件：**
- 修改：`novalon-manage-web/e2e/pages/UserManagementPage.ts`

- [ ] **步骤 1：更新构造函数中的选择器**

根据诊断结果，更新选择器：

```typescript
constructor(page: Page) {
  this.page = page;
  
  // 使用更健壮的选择器
  this.table = page.locator('.el-table').first();
  this.createUserButton = page.getByRole('button', { name: '新增用户' });
  this.searchInput = page.getByPlaceholder('搜索用户名或邮箱').or(page.locator('input[placeholder*="搜索"]'));
  this.searchButton = page.getByRole('button', { name: '搜索' });
  this.successMessage = page.locator('.el-message--success').or(page.locator('.el-message'));
  this.pagination = page.locator('.el-pagination');
  this.nextPageButton = page.locator('.el-pagination .btn-next');
  this.prevPageButton = page.locator('.el-pagination .btn-prev');
}
```

- [ ] **步骤 2：更新其他方法中的选择器**

检查并更新所有使用选择器的方法，确保使用最佳实践。

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/pages/UserManagementPage.ts
git commit -m "fix: update UserManagementPage selectors for better reliability"
```

---

### 任务 15：更新其他Page Object类的选择器

**文件：**
- 修改：所有其他Page Object类

- [ ] **步骤 1：批量更新选择器**

按照任务14的模式，更新所有其他Page Object类的选择器。

- [ ] **步骤 2：提交修改**

```bash
git add novalon-manage-web/e2e/pages/*.ts
git commit -m "fix: update all Page Object selectors for better reliability"
```

---

### 任务 16：运行第二阶段测试验证

**文件：**
- 无文件修改

- [ ] **步骤 1：运行完整测试套件**

```bash
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts --project=chromium --retries=0
```

预期：测试通过率提升至90%以上（至少47个测试用例通过）

- [ ] **步骤 2：收集测试结果**

```bash
cat test-results/results.json | jq '.suites[0].suites[0].suites[] | {title: .title, passed: [.specs[] | select(.ok == true)] | length, total: (.specs | length)}'
```

- [ ] **步骤 3：分析剩余失败原因**

记录第二阶段修复后的测试通过率和剩余失败原因。

---

## 第三阶段：性能优化

**目标：** 测试通过率达到100%，执行时间减少30%以上

---

### 任务 17：优化全局setup时间

**文件：**
- 修改：`novalon-manage-web/e2e/global-setup.ts`

- [ ] **步骤 1：读取当前global-setup代码**

```bash
cat novalon-manage-web/e2e/global-setup.ts
```

- [ ] **步骤 2：优化健康检查间隔**

将健康检查间隔从1000ms改为500ms：

```typescript
// 优化前
await new Promise(resolve => setTimeout(resolve, 1000));

// 优化后
await new Promise(resolve => setTimeout(resolve, 500));
```

- [ ] **步骤 3：减少最大等待时间**

将最大等待时间从60秒改为30秒：

```typescript
const maxAttempts = 30; // 从60改为30
```

- [ ] **步骤 4：提交修改**

```bash
git add novalon-manage-web/e2e/global-setup.ts
git commit -m "perf: optimize global setup time"
```

---

### 任务 18：优化页面加载等待策略

**文件：**
- 修改：`novalon-manage-web/e2e/system-integration-test.spec.ts`

- [ ] **步骤 1：查找所有waitForTimeout调用**

```bash
grep -n "waitForTimeout" novalon-manage-web/e2e/system-integration-test.spec.ts
```

- [ ] **步骤 2：替换固定等待为智能等待**

将所有`waitForTimeout`替换为更智能的等待策略：

```typescript
// 优化前
await page.waitForTimeout(2000);

// 优化后
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('.el-table', { state: 'visible' });
```

- [ ] **步骤 3：提交修改**

```bash
git add novalon-manage-web/e2e/system-integration-test.spec.ts
git commit -m "perf: replace fixed waits with smart waits"
```

---

### 任务 19：运行最终测试验证

**文件：**
- 无文件修改

- [ ] **步骤 1：运行完整测试套件**

```bash
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts --project=chromium --retries=0
```

预期：所有52个测试用例通过，执行时间在12分钟以内

- [ ] **步骤 2：生成最终测试报告**

```bash
cat test-results/results.json | jq '.suites[0].suites[0].suites[] | {title: .title, passed: [.specs[] | select(.ok == true)] | length, total: (.specs | length)}'
```

- [ ] **步骤 3：记录最终结果**

```markdown
# 最终测试结果
- 总测试数：52
- 通过数：[实际通过数]
- 失败数：[实际失败数]
- 通过率：[实际通过率]%
- 执行时间：[实际执行时间]

# 性能提升
- 执行时间减少：[百分比]%
- Setup时间减少：[百分比]%
```

---

### 任务 20：生成最终报告并提交

**文件：**
- 创建：`docs/superpowers/reports/2026-04-04-e2e-test-optimization-report.md`

- [ ] **步骤 1：创建测试报告**

创建详细的测试报告，包含：
- 测试通过率统计
- 执行时间统计
- 修复的问题列表
- 性能提升数据

- [ ] **步骤 2：提交最终报告**

```bash
git add docs/superpowers/reports/2026-04-04-e2e-test-optimization-report.md
git commit -m "docs: add E2E test optimization final report"
```

- [ ] **步骤 3：推送所有修改到远程仓库**

```bash
git push origin feature/operation-log-optimization
```

---

## 验收标准

### 功能验收
- ✅ 所有52个测试用例100%通过
- ✅ 测试覆盖所有核心业务流程
- ✅ 测试报告清晰展示测试结果

### 性能验收
- ✅ 测试执行时间在12分钟以内
- ✅ 全局setup时间在30秒以内
- ✅ 单个测试用例平均执行时间在20秒以内

### 质量验收
- ✅ 所有Page Object类有完善的错误处理
- ✅ 所有选择器使用最佳实践
- ✅ 测试代码有清晰的注释和文档

---

**计划结束**
