first commit

This commit is contained in:
2025-11-04 16:29:07 +08:00
commit 8ee74625c7
19 changed files with 4562 additions and 0 deletions

361
ARCHITECTURE.md Normal file
View File

@ -0,0 +1,361 @@
# 项目架构说明
## 设计理念
本项目采用 **Page Object Model (POM)** 设计模式,遵循以下原则:
1. **关注点分离**:页面逻辑与测试逻辑分离
2. **DRY 原则**:避免重复代码
3. **单一职责**:每个类只负责一个页面或功能
4. **可测试性**:易于编写和维护测试
5. **可扩展性**:便于添加新功能
## 架构图
```
┌─────────────────────────────────────────────────┐
│ 测试文件层 │
│ (文书管理-refactored.spec.ts) │
│ - 组织测试流程 │
│ - 使用 Page Objects │
│ - 错误处理 │
└─────────────────┬───────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Page Object 层 │
│ - LoginPage (登录) │
│ - StudentPage (学生管理) │
│ - DreamiExplorePage (AI聊天) │
│ - EssayWritingPage (文书写作) │
│ - BasePage (基础页面类) │
└─────────────────┬───────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ 工具层 │
│ - ErrorHandler (错误处理) │
│ - 其他工具类... │
└─────────────────┬───────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ 配置层 │
│ - TestConfig (测试配置) │
│ - 环境变量、超时设置、测试数据 │
└─────────────────────────────────────────────────┘
```
## 核心组件
### 1. 配置层 (config/)
**职责**:集中管理所有配置信息
#### test.config.ts
```typescript
export const TestConfig = {
env: { ... }, // 环境配置
credentials: { ... }, // 登录凭证
timeouts: { ... }, // 超时设置
testData: { ... }, // 测试数据
waits: { ... }, // 等待时间
report: { ... }, // 报告配置
}
```
**优势**
- ✅ 环境切换方便
- ✅ 配置集中管理
- ✅ 避免硬编码
- ✅ 易于维护
### 2. Page Object 层 (pages/)
**职责**:封装页面操作,提供高级 API
#### BasePage.ts
基础页面类,所有页面对象的父类
```typescript
export class BasePage {
protected page: Page;
protected config = TestConfig;
// 通用方法
async waitForPageStable() { }
async goto(url: string) { }
async click(selector: string) { }
// ...
}
```
#### LoginPage.ts
登录页面对象
```typescript
export class LoginPage extends BasePage {
async visitHomePage() { }
async clickLoginButton() { }
async login(email, password) { }
async performLogin() { }
}
```
**设计特点**
- 继承 BasePage 获取通用功能
- 方法名语义化,易于理解
- 封装页面元素定位
- 提供高级业务方法
#### StudentPage.ts
学生管理页面对象
```typescript
export class StudentPage extends BasePage {
async goToStudentWorkbench() { }
async createNewStudent(studentData) { }
}
```
#### EssayWritingPage.ts
文书写作页面对象(最复杂)
```typescript
export class EssayWritingPage extends BasePage {
// 基础操作
async enterEssayWriting() { }
async addMaterial(title, content, expectedText) { }
// AI 生成功能
async generateEssayIdea() { }
async generateEssay() { }
async generateOutline() { }
async generateDraft(level, length) { }
// 检查功能
async performGrammarCheck() { }
async performPlagiarismCheck() { }
async performAIDetection() { }
async performHumanize() { }
async performPolish() { }
async performGetRated() { }
async performImprovementCheck() { }
}
```
**优势**
- ✅ 业务逻辑清晰
- ✅ 方法可复用
- ✅ UI 变化只需修改 Page Object
- ✅ 测试文件更简洁
### 3. 工具层 (utils/)
**职责**:提供通用工具和辅助功能
#### ErrorHandler.ts
错误处理工具类
```typescript
export class ErrorHandler {
private errors: ErrorRecord[] = [];
// 记录错误
recordError(stepName, error, page) { }
// 执行步骤并捕获错误
async executeStep(stepName, stepFunction, page) { }
// 生成错误报告
generateErrorReport() { }
// 打印摘要
printSummary() { }
}
```
**功能**
- ✅ 自动捕获并记录错误
- ✅ 清理错误信息,去除技术细节
- ✅ 生成友好的错误报告
- ✅ 允许测试继续执行
### 4. 测试文件层
**职责**:组织测试流程,调用 Page Objects
#### 文书管理-refactored.spec.ts
```typescript
test('文书管理完整流程测试', async ({ page }) => {
// 初始化
const errorHandler = new ErrorHandler(TestConfig.credentials);
const loginPage = new LoginPage(page);
const essayWritingPage = new EssayWritingPage(page);
// 测试流程
await executeStep('访问首页', async () => {
await loginPage.visitHomePage();
});
await executeStep('生成 Essay', async () => {
await essayWritingPage.generateEssay();
});
// 生成报告
errorHandler.printSummary();
});
```
**特点**
- ✅ 代码清晰易读
- ✅ 业务流程一目了然
- ✅ 错误处理自动化
- ✅ 配置与代码分离
## 数据流
```
测试开始
读取 TestConfig
初始化 Page Objects
执行测试步骤 (executeStep)
调用 Page Object 方法
Page Object 执行页面操作
发生错误?
├─ 是 → ErrorHandler 记录错误 → 继续下一步
└─ 否 → 继续下一步
所有步骤完成
生成错误报告
测试结束
```
## 扩展指南
### 添加新页面
1. **创建 Page Object**
```typescript
// e2e/pages/NewPage.ts
import { Page, expect } from '@playwright/test';
import { BasePage } from './BasePage';
export class NewPage extends BasePage {
constructor(page: Page) {
super(page);
}
async yourMethod(): Promise<void> {
// 实现页面操作
}
}
```
2. **在测试中使用**
```typescript
import { NewPage } from './pages/NewPage';
test('your test', async ({ page }) => {
const newPage = new NewPage(page);
await newPage.yourMethod();
});
```
### 添加新配置
`test.config.ts` 中添加:
```typescript
export const TestConfig = {
// ... 现有配置
newConfig: {
// 新配置项
}
}
```
### 添加新工具类
```typescript
// e2e/utils/YourUtil.ts
export class YourUtil {
// 实现工具方法
}
```
## 最佳实践
### 1. Page Object 设计
- ✅ 一个页面一个类
- ✅ 方法返回 Promise<void>
- ✅ 使用描述性方法名
- ✅ 避免在 Page Object 中写断言(除非是验证页面状态)
### 2. 测试文件编写
- ✅ 使用 executeStep 包装每个步骤
- ✅ 步骤名称清晰描述操作
- ✅ 复杂流程拆分为多个步骤
- ✅ 在测试末尾生成报告
### 3. 配置管理
- ✅ 不要硬编码任何配置值
- ✅ 环境相关的配置放在 env 中
- ✅ 测试数据放在 testData 中
- ✅ 超时设置放在 timeouts 中
### 4. 错误处理
- ✅ 所有关键步骤都用 executeStep 包装
- ✅ 不要在 Page Object 中处理错误
- ✅ 让错误冒泡到测试层处理
- ✅ 记录足够的错误上下文信息
## 代码复用
### 前后对比
**重构前**
```typescript
// 代码重复,难以维护
await page.getByRole('button', { name: 'Add Material' }).click();
await page.getByRole('menuitem', { name: 'Manual Add' }).click();
await page.getByRole('textbox', { name: 'Title' }).fill('title');
// ... 10+ 行相似代码
```
**重构后**
```typescript
// 简洁清晰,易于维护
await essayWritingPage.addMaterial(
TestConfig.testData.material.title,
TestConfig.testData.material.content,
TestConfig.testData.material.expectedButtonText
);
```
## 性能优化
- Page Object 方法中使用合理的超时
- 配置中集中管理超时时间
- 避免不必要的等待
- 使用页面对象缓存(如需要)
## 总结
这个架构具有以下优势:
1. **可维护性**:模块化设计,职责清晰
2. **可扩展性**:易于添加新功能
3. **可读性**:代码清晰,易于理解
4. **可测试性**:每个组件独立可测
5. **健壮性**:完善的错误处理机制
通过这种架构,测试代码变得像文档一样易读,维护成本大大降低。