diff --git a/docs/plans/2026-02-28-e2e-test-unification-design.md b/docs/plans/2026-02-28-e2e-test-unification-design.md new file mode 100644 index 0000000..f1c9ce0 --- /dev/null +++ b/docs/plans/2026-02-28-e2e-test-unification-design.md @@ -0,0 +1,944 @@ +# Novalon Website E2E测试统一方案设计 + +**创建时间**: 2026-02-28 +**目标**: 统一E2E测试框架,从Python+Pytest迁移到TypeScript+Playwright,建立金融级网站完整的测试体系 + +--- + +## 一、背景与目标 + +### 当前状态 +- **两套测试框架并存**: + - TypeScript + Playwright (`e2e/` 目录) + - Python + Pytest (`e2e-tests/` 目录) +- **维护成本高**: 需要维护两套技术栈 +- **测试覆盖不完整**: 部分测试场景缺失或重复 + +### 核心目标 +1. **统一技术栈**: 完全迁移到Playwright,与Next.js项目技术栈一致 +2. **全面测试覆盖**: 建立业务流程、性能、安全、可访问性完整测试体系 +3. **金融级质量**: 满足金融行业对安全、合规、可靠性的高要求 +4. **CI/CD集成**: 建立分层测试流程,平衡速度和覆盖率 + +--- + +## 二、技术选型决策 + +### 选择: TypeScript + Playwright + +**决策理由**: +- ✅ 与项目技术栈一致(Next.js + TypeScript) +- ✅ 可共享类型定义,更好的类型安全 +- ✅ Playwright功能强大,支持多浏览器、移动端、视觉测试 +- ✅ 社区活跃,文档完善,生态成熟 +- ✅ 原生支持并行执行,性能优异 + +**放弃: Python + Pytest** +- ❌ 与项目技术栈不一致,增加维护成本 +- ❌ 无法共享类型定义,降低开发效率 +- ❌ 需要维护两套依赖和环境 + +--- + +## 三、整体架构设计 + +### 3.1 分层架构 + +``` +┌─────────────────────────────────────────────────┐ +│ 报告与监控层 (Reports & Monitoring) │ +│ HTML报告 | JSON/JUnit报告 | 性能指标 | 趋势分析 │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ 测试用例层 (Test Cases) │ +│ Smoke | Regression | Performance | Security │ +│ Accessibility | Visual | Mobile │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ 页面对象层 (Page Objects) │ +│ BasePage | HomePage | ContactPage | Products │ +│ Components (Header, Footer, Form) │ +└─────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────┐ +│ 基础设施层 (Infrastructure) │ +│ Playwright配置 | 测试数据 | 工具库 | Fixtures │ +└─────────────────────────────────────────────────┘ +``` + +### 3.2 目录结构 + +``` +e2e/ +├── src/ +│ ├── fixtures/ # 测试夹具 +│ │ ├── base.fixture.ts # 基础fixture +│ │ ├── a11y.fixture.ts # 可访问性fixture +│ │ └── auth.fixture.ts # 认证fixture(如需要) +│ ├── pages/ # 页面对象 +│ │ ├── BasePage.ts # 基础页面 +│ │ ├── HomePage.ts # 首页 +│ │ ├── ContactPage.ts # 联系页面 +│ │ ├── ProductsPage.ts # 产品页面 +│ │ ├── ServicesPage.ts # 服务页面 +│ │ ├── AboutPage.ts # 关于页面 +│ │ ├── CasesPage.ts # 案例页面 +│ │ ├── SolutionsPage.ts # 解决方案页面 +│ │ └── NewsPage.ts # 新闻页面 +│ ├── tests/ # 测试用例 +│ │ ├── smoke/ # 冒烟测试 +│ │ ├── regression/ # 回归测试 +│ │ ├── performance/ # 性能测试 +│ │ ├── security/ # 安全测试 +│ │ ├── accessibility/ # 可访问性测试 +│ │ ├── visual/ # 视觉回归测试 +│ │ ├── mobile/ # 移动端测试 +│ │ ├── responsive/ # 响应式测试 +│ │ └── error-handling/ # 错误处理测试 +│ ├── types/ # 类型定义 +│ │ └── index.ts # 共享类型 +│ └── utils/ # 工具库 +│ ├── PerformanceMonitor.ts # 性能监控 +│ ├── TestDataGenerator.ts # 测试数据生成 +│ ├── devices.ts # 设备配置 +│ └── helpers.ts # 辅助函数 +├── test-data/ # 测试数据文件 +│ ├── contact-form.json # 联系表单数据 +│ ├── products.json # 产品数据 +│ └── performance-budgets.json # 性能预算 +├── playwright.config.ts # Playwright配置 +├── package.json # 依赖管理 +└── tsconfig.json # TypeScript配置 +``` + +--- + +## 四、测试分层策略 + +### 4.1 测试金字塔 + +``` + ┌─────────┐ + │ Security│ (每周/发布前) + │ Access │ 10-15分钟 + └─────────┘ + ┌───────────────┐ + │ Performance │ (每日/发布前) + │ 10-20分钟 │ + └───────────────┘ + ┌─────────────────────┐ + │ Regression │ (PR合并前/每日) + │ 15-30分钟 │ + └─────────────────────┘ + ┌───────────────────────────┐ + │ Smoke │ (每次提交) + │ < 5分钟 │ + └───────────────────────────┘ +``` + +### 4.2 各层测试详解 + +#### Level 1: Smoke Tests(冒烟测试) + +**执行频率**: 每次代码提交 +**执行时间**: < 5分钟 +**标签**: `@smoke` + +**覆盖范围**: +- ✅ 所有关键页面可访问性(首页、产品、服务、联系) +- ✅ 核心导航功能 +- ✅ 关键表单提交(联系表单) +- ✅ 页面基本渲染(无JS错误) + +**测试用例**: +```typescript +test.describe('Smoke Tests @smoke', () => { + test('首页可访问', async ({ page }) => { + await homePage.goto(); + await expect(page).toHaveTitle(/Novalon/); + }); + + test('导航功能正常', async ({ page }) => { + await homePage.goto(); + await homePage.navigateTo('产品'); + await expect(page).toHaveURL(/products/); + }); + + test('联系表单可提交', async ({ page }) => { + await contactPage.goto(); + await contactPage.fillForm({ + name: '测试用户', + email: 'test@example.com', + message: '测试消息' + }); + await contactPage.submit(); + await expect(contactPage.successMessage).toBeVisible(); + }); +}); +``` + +#### Level 2: Regression Tests(回归测试) + +**执行频率**: PR合并前、每日构建 +**执行时间**: 15-30分钟 +**标签**: `@regression` + +**覆盖范围**: +- ✅ 所有业务流程完整测试 +- ✅ 表单验证(必填项、格式校验、错误提示) +- ✅ 页面间跳转和数据传递 +- ✅ 响应式布局(桌面/平板/移动端) +- ✅ 多浏览器兼容性 + +**测试用例**: +```typescript +test.describe('Contact Form Regression @regression', () => { + test('表单验证 - 必填项', async ({ page }) => { + await contactPage.goto(); + await contactPage.submit(); + await expect(contactPage.nameError).toHaveText('请输入姓名'); + await expect(contactPage.emailError).toHaveText('请输入邮箱'); + }); + + test('表单验证 - 邮箱格式', async ({ page }) => { + await contactPage.goto(); + await contactPage.fillEmail('invalid-email'); + await contactPage.submit(); + await expect(contactPage.emailError).toHaveText('邮箱格式不正确'); + }); + + test('表单提交成功', async ({ page }) => { + await contactPage.goto(); + await contactPage.fillForm(testData.validContact); + await contactPage.submit(); + await expect(contactPage.successMessage).toBeVisible(); + }); +}); +``` + +#### Level 3: Performance Tests(性能测试) + +**执行频率**: 每日构建、发布前 +**执行时间**: 10-20分钟 +**标签**: `@performance` + +**覆盖范围**: +- ✅ 页面加载时间(FCP、LCP、TTI) +- ✅ 资源大小优化(图片、JS、CSS) +- ✅ 网络请求数量和瀑布流 +- ✅ 核心交互响应时间 +- ✅ 性能预算验证 + +**性能预算**: +```json +{ + "performanceBudgets": { + "home": { + "loadTime": 3000, + "fcP": 1500, + "lcp": 2500, + "tti": 3500, + "totalSize": 1500000 + }, + "contact": { + "loadTime": 2500, + "fcp": 1200, + "lcp": 2000, + "tti": 3000, + "totalSize": 1200000 + } + } +} +``` + +**测试用例**: +```typescript +test.describe('Performance Tests @performance', () => { + test('首页性能预算', async ({ page }) => { + const metrics = await performanceMonitor.measurePageLoad(page, '/'); + + expect(metrics.loadTime).toBeLessThan(budgets.home.loadTime); + expect(metrics.fcp).toBeLessThan(budgets.home.fcp); + expect(metrics.lcp).toBeLessThan(budgets.home.lcp); + }); + + test('图片优化验证', async ({ page }) => { + await page.goto('/'); + const images = await page.$$eval('img', imgs => + imgs.map(img => ({ + src: img.src, + naturalWidth: img.naturalWidth, + naturalHeight: img.naturalHeight, + displayWidth: img.width, + displayHeight: img.height + })) + ); + + for (const img of images) { + expect(img.naturalWidth).toBeLessThanOrEqual(img.displayWidth * 2); + } + }); +}); +``` + +#### Level 4: Security Tests(安全测试) + +**执行频率**: 每周、发布前 +**执行时间**: 10-15分钟 +**标签**: `@security` + +**覆盖范围**: +- ✅ XSS漏洞检测(表单输入) +- ✅ CSRF保护验证 +- ✅ 安全头验证(CSP、HSTS等) +- ✅ 敏感数据处理(联系表单数据加密) +- ✅ HTTPS强制跳转 + +**测试用例**: +```typescript +test.describe('Security Tests @security', () => { + test('XSS防护 - 联系表单', async ({ page }) => { + await contactPage.goto(); + await contactPage.fillForm({ + name: '', + email: 'test@example.com', + message: '' + }); + await contactPage.submit(); + + const pageContent = await page.content(); + expect(pageContent).not.toContain('