22 KiB
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:检查路由配置文件
读取路由配置文件,确认所有测试用例涉及的页面都已配置:
cat novalon-manage-web/src/router/index.ts
预期:看到所有路由配置(/users, /roles, /menus, /sys/config, /dict, /files, /loginlog, /oplog, /exceptionlog)
- 步骤 2:验证页面组件是否存在
检查每个路由对应的Vue组件是否存在:
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:记录缺失的页面
如果发现缺失的页面,记录下来:
# 缺失页面列表
- 无(所有页面都已实现)
任务 2:优化UserManagementPage导航
文件:
-
修改:
novalon-manage-web/e2e/pages/UserManagementPage.ts -
步骤 1:读取当前UserManagementPage代码
cat novalon-manage-web/e2e/pages/UserManagementPage.ts
- 步骤 2:优化goto方法
修改goto方法,添加更健壮的导航逻辑:
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方法
添加智能等待表格加载的方法:
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/RoleManagementPage.ts
- 步骤 2:优化goto方法
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方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/MenuManagementPage.ts
- 步骤 2:优化goto方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/SystemConfigPage.ts
- 步骤 2:优化goto方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/DictionaryManagementPage.ts
- 步骤 2:优化goto方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/FileManagementPage.ts
- 步骤 2:优化goto方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/OperationLogPage.ts
- 步骤 2:优化goto方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/LoginLogPage.ts
- 步骤 2:优化goto方法
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:提交修改
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代码
cat novalon-manage-web/e2e/pages/ExceptionLogPage.ts
- 步骤 2:优化goto方法
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:提交修改
git add novalon-manage-web/e2e/pages/ExceptionLogPage.ts
git commit -m "fix: optimize ExceptionLogPage navigation with better error handling"
任务 11:运行第一阶段测试验证
文件:
-
无文件修改
-
步骤 1:运行完整测试套件
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts --project=chromium --retries=0
预期:测试通过率提升至50%以上(至少26个测试用例通过)
- 步骤 2:收集测试结果
查看测试报告:
cat test-results/results.json | jq '.suites[0].suites[0].suites[] | {title: .title, passed: [.specs[] | select(.ok == true)] | length, total: (.specs | length)}'
- 步骤 3:分析剩余失败原因
记录第一阶段修复后的测试通过率和剩余失败原因:
# 第一阶段测试结果
- 总测试数:52
- 通过数:[实际通过数]
- 失败数:[实际失败数]
- 通过率:[实际通过率]%
# 剩余失败原因分析
1. 选择器问题:[数量]个
2. 其他问题:[数量]个
第二阶段:选择器精准化
目标: 测试通过率提升至90%以上(至少47个测试用例通过)
任务 12:启用Playwright trace功能
文件:
-
修改:
novalon-manage-web/playwright.config.ts -
步骤 1:读取当前playwright配置
cat novalon-manage-web/playwright.config.ts
- 步骤 2:启用trace功能
在use配置中添加trace选项:
use: {
// ... 其他配置
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
}
- 步骤 3:提交修改
git add novalon-manage-web/playwright.config.ts
git commit -m "feat: enable Playwright trace for debugging"
任务 13:诊断失败测试的选择器问题
文件:
-
无文件修改
-
步骤 1:运行失败测试并生成trace
选择一个失败的测试用例运行:
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts:104 --project=chromium --trace on
- 步骤 2:查看trace报告
npx playwright show-trace test-results/[trace-file].zip
- 步骤 3:记录选择器问题
根据trace报告,记录选择器问题:
# 选择器问题列表
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:更新构造函数中的选择器
根据诊断结果,更新选择器:
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:提交修改
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:提交修改
git add novalon-manage-web/e2e/pages/*.ts
git commit -m "fix: update all Page Object selectors for better reliability"
任务 16:运行第二阶段测试验证
文件:
-
无文件修改
-
步骤 1:运行完整测试套件
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts --project=chromium --retries=0
预期:测试通过率提升至90%以上(至少47个测试用例通过)
- 步骤 2:收集测试结果
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代码
cat novalon-manage-web/e2e/global-setup.ts
- 步骤 2:优化健康检查间隔
将健康检查间隔从1000ms改为500ms:
// 优化前
await new Promise(resolve => setTimeout(resolve, 1000));
// 优化后
await new Promise(resolve => setTimeout(resolve, 500));
- 步骤 3:减少最大等待时间
将最大等待时间从60秒改为30秒:
const maxAttempts = 30; // 从60改为30
- 步骤 4:提交修改
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调用
grep -n "waitForTimeout" novalon-manage-web/e2e/system-integration-test.spec.ts
- 步骤 2:替换固定等待为智能等待
将所有waitForTimeout替换为更智能的等待策略:
// 优化前
await page.waitForTimeout(2000);
// 优化后
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('.el-table', { state: 'visible' });
- 步骤 3:提交修改
git add novalon-manage-web/e2e/system-integration-test.spec.ts
git commit -m "perf: replace fixed waits with smart waits"
任务 19:运行最终测试验证
文件:
-
无文件修改
-
步骤 1:运行完整测试套件
cd novalon-manage-web
npx playwright test system-integration-test.spec.ts --project=chromium --retries=0
预期:所有52个测试用例通过,执行时间在12分钟以内
- 步骤 2:生成最终测试报告
cat test-results/results.json | jq '.suites[0].suites[0].suites[] | {title: .title, passed: [.specs[] | select(.ok == true)] | length, total: (.specs | length)}'
- 步骤 3:记录最终结果
# 最终测试结果
- 总测试数:52
- 通过数:[实际通过数]
- 失败数:[实际失败数]
- 通过率:[实际通过率]%
- 执行时间:[实际执行时间]
# 性能提升
- 执行时间减少:[百分比]%
- Setup时间减少:[百分比]%
任务 20:生成最终报告并提交
文件:
-
创建:
docs/superpowers/reports/2026-04-04-e2e-test-optimization-report.md -
步骤 1:创建测试报告
创建详细的测试报告,包含:
-
测试通过率统计
-
执行时间统计
-
修复的问题列表
-
性能提升数据
-
步骤 2:提交最终报告
git add docs/superpowers/reports/2026-04-04-e2e-test-optimization-report.md
git commit -m "docs: add E2E test optimization final report"
- 步骤 3:推送所有修改到远程仓库
git push origin feature/operation-log-optimization
验收标准
功能验收
- ✅ 所有52个测试用例100%通过
- ✅ 测试覆盖所有核心业务流程
- ✅ 测试报告清晰展示测试结果
性能验收
- ✅ 测试执行时间在12分钟以内
- ✅ 全局setup时间在30秒以内
- ✅ 单个测试用例平均执行时间在20秒以内
质量验收
- ✅ 所有Page Object类有完善的错误处理
- ✅ 所有选择器使用最佳实践
- ✅ 测试代码有清晰的注释和文档
计划结束