feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,460 @@
|
||||
# Uniapp E2E测试使用指南
|
||||
|
||||
## 概述
|
||||
|
||||
本E2E测试工具为everything-is-suitable-uniapp小程序提供全面的端到端测试解决方案,基于Playwright构建,支持多浏览器、多平台测试,并提供详细的测试报告。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
e2e/uniapp/
|
||||
├── pages/ # 页面对象模型
|
||||
│ ├── base-page.ts # 基础页面类
|
||||
│ ├── calendar-page.ts # 万年历页面
|
||||
│ ├── almanac-page.ts # 黄历页面
|
||||
│ ├── user-page.ts # 用户中心页面
|
||||
│ └── bottom-navigation.ts # 底部导航栏
|
||||
├── navigation.spec.ts # 页面导航测试
|
||||
├── calendar.spec.ts # 万年历页面测试
|
||||
├── almanac.spec.ts # 黄历页面测试
|
||||
├── user.spec.ts # 用户中心页面测试
|
||||
├── data-loading.spec.ts # 数据加载测试
|
||||
├── state-update.spec.ts # 状态更新测试
|
||||
├── boundary.spec.ts # 边界条件测试
|
||||
├── test-reporter.ts # 测试报告生成器
|
||||
├── global-setup.ts # 全局测试设置
|
||||
└── global-teardown.ts # 全局测试清理
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 安装依赖
|
||||
|
||||
```bash
|
||||
cd everything-is-suitable-test
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. 启动Uniapp应用
|
||||
|
||||
在另一个终端中启动Uniapp应用:
|
||||
|
||||
```bash
|
||||
cd ../everything-is-suitable-uniapp
|
||||
npm run dev:h5
|
||||
```
|
||||
|
||||
### 3. 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有Uniapp E2E测试
|
||||
npm run test:e2e:uniapp
|
||||
|
||||
# 运行特定测试文件
|
||||
npx playwright test --config=playwright.uniapp.config.ts e2e/uniapp/navigation.spec.ts
|
||||
|
||||
# 运行特定测试用例
|
||||
npx playwright test --config=playwright.uniapp.config.ts -g "底部导航栏切换测试"
|
||||
|
||||
# 调试模式运行
|
||||
npm run test:e2e:uniapp:debug
|
||||
|
||||
# UI模式运行
|
||||
npm run test:e2e:uniapp:ui
|
||||
|
||||
# 有头模式运行(显示浏览器)
|
||||
npm run test:e2e:uniapp:headed
|
||||
```
|
||||
|
||||
### 4. 查看测试报告
|
||||
|
||||
```bash
|
||||
# 查看Playwright HTML报告
|
||||
npm run test:e2e:uniapp:report
|
||||
```
|
||||
|
||||
## 测试用例
|
||||
|
||||
### 页面导航测试 (navigation.spec.ts)
|
||||
|
||||
- **TC-001**: 底部导航栏切换测试
|
||||
- **TC-002**: 页面标题显示测试
|
||||
|
||||
### 万年历页面测试 (calendar.spec.ts)
|
||||
|
||||
- **TC-003**: 日历月份切换测试
|
||||
- **TC-004**: 日期选择测试
|
||||
- **TC-005**: 农历信息显示测试
|
||||
|
||||
### 黄历页面测试 (almanac.spec.ts)
|
||||
|
||||
- **TC-006**: 黄历日期切换测试
|
||||
- **TC-007**: 黄历信息显示测试
|
||||
|
||||
### 用户中心页面测试 (user.spec.ts)
|
||||
|
||||
- **TC-008**: 用户信息显示测试
|
||||
- **TC-009**: 菜单导航测试
|
||||
|
||||
### 数据加载测试 (data-loading.spec.ts)
|
||||
|
||||
- **TC-012**: 黄历数据加载测试
|
||||
- **TC-013**: 日历数据加载测试
|
||||
|
||||
### 状态更新测试 (state-update.spec.ts)
|
||||
|
||||
- **TC-014**: 选中日期状态更新测试
|
||||
- **TC-015**: 导航栏状态更新测试
|
||||
|
||||
### 边界条件测试 (boundary.spec.ts)
|
||||
|
||||
- **TC-016**: 月份边界测试
|
||||
- **TC-017**: 日期边界测试
|
||||
- **TC-018**: 表单验证测试
|
||||
|
||||
## 页面对象模型
|
||||
|
||||
### BasePage
|
||||
|
||||
所有页面对象的基类,提供通用的页面操作方法:
|
||||
|
||||
```typescript
|
||||
import { BasePage } from './pages/base-page';
|
||||
|
||||
const page = new BasePage(page);
|
||||
await page.navigate('/pages/calendar/index');
|
||||
await page.waitForLoad();
|
||||
await page.clickElement('.button');
|
||||
await page.fillInput('.input', 'value');
|
||||
```
|
||||
|
||||
### CalendarPage
|
||||
|
||||
万年历页面对象:
|
||||
|
||||
```typescript
|
||||
import { CalendarPage } from './pages/calendar-page';
|
||||
|
||||
const calendarPage = new CalendarPage(page);
|
||||
await calendarPage.navigate();
|
||||
await calendarPage.clickNextMonth();
|
||||
await calendarPage.clickDay(15);
|
||||
const lunarDate = await calendarPage.getLunarDate();
|
||||
```
|
||||
|
||||
### AlmanacPage
|
||||
|
||||
黄历页面对象:
|
||||
|
||||
```typescript
|
||||
import { AlmanacPage } from './pages/almanac-page';
|
||||
|
||||
const almanacPage = new AlmanacPage(page);
|
||||
await almanacPage.navigate();
|
||||
await almanacPage.clickNextDate();
|
||||
const almanacInfo = await almanacPage.getAllAlmanacInfo();
|
||||
```
|
||||
|
||||
### UserPage
|
||||
|
||||
用户中心页面对象:
|
||||
|
||||
```typescript
|
||||
import { UserPage } from './pages/user-page';
|
||||
|
||||
const userPage = new UserPage(page);
|
||||
await userPage.navigate();
|
||||
const userName = await userPage.getUserName();
|
||||
await userPage.clickMenuItem(0);
|
||||
```
|
||||
|
||||
### BottomNavigation
|
||||
|
||||
底部导航栏对象:
|
||||
|
||||
```typescript
|
||||
import { BottomNavigation } from './pages/bottom-navigation';
|
||||
|
||||
const bottomNavigation = new BottomNavigation(page);
|
||||
await bottomNavigation.clickTab('almanac');
|
||||
const isActive = await bottomNavigation.isTabActive('almanac');
|
||||
```
|
||||
|
||||
## 测试报告
|
||||
|
||||
### Playwright报告
|
||||
|
||||
Playwright自动生成HTML报告,包含:
|
||||
- 测试执行摘要
|
||||
- 每个测试的详细信息
|
||||
- 失败测试的截图和视频
|
||||
- 性能指标
|
||||
|
||||
### 自定义报告
|
||||
|
||||
使用`test-reporter.ts`生成自定义报告:
|
||||
|
||||
```typescript
|
||||
import { UniappTestReporter } from './test-reporter';
|
||||
|
||||
const reporter = new UniappTestReporter();
|
||||
reporter.addTestSuite('测试套件名称', [
|
||||
{
|
||||
testName: '测试用例名称',
|
||||
status: 'passed',
|
||||
duration: 1000,
|
||||
}
|
||||
]);
|
||||
|
||||
await reporter.generateJSONReport('test-results/uniapp-report.json');
|
||||
await reporter.generateHTMLReport('test-results/uniapp-report.html');
|
||||
await reporter.generateMarkdownReport('test-results/uniapp-report.md');
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
### Playwright配置
|
||||
|
||||
配置文件:`playwright.uniapp.config.ts`
|
||||
|
||||
主要配置项:
|
||||
- `testDir`: 测试文件目录
|
||||
- `baseURL`: 应用基础URL
|
||||
- `projects`: 浏览器项目配置
|
||||
- `webServer`: 开发服务器配置
|
||||
|
||||
### 环境变量
|
||||
|
||||
- `BASE_URL`: 应用基础URL
|
||||
- `CI`: 是否在CI环境中运行
|
||||
- `NODE_ENV`: Node环境
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 测试用例编写
|
||||
|
||||
- 使用描述性的测试名称
|
||||
- 遵循AAA模式(Arrange-Act-Assert)
|
||||
- 使用页面对象而不是直接操作元素
|
||||
- 添加适当的等待和断言
|
||||
|
||||
```typescript
|
||||
test('应该能够切换到黄历页面', async ({ page }) => {
|
||||
await calendarPage.navigate();
|
||||
await bottomNavigation.clickTab('almanac');
|
||||
|
||||
const title = await page.title();
|
||||
expect(title).toContain('黄历');
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 页面对象使用
|
||||
|
||||
- 将选择器封装在页面对象中
|
||||
- 实现业务逻辑方法
|
||||
- 保持页面对象的独立性
|
||||
|
||||
```typescript
|
||||
export class CalendarPage extends BasePage {
|
||||
private readonly selectors = {
|
||||
prevMonthButton: '[data-testid="prev-month"]',
|
||||
nextMonthButton: '[data-testid="next-month"]',
|
||||
};
|
||||
|
||||
async clickNextMonth() {
|
||||
await this.clickElement(this.selectors.nextMonthButton);
|
||||
await this.waitForLoad();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 测试数据管理
|
||||
|
||||
- 使用测试数据生成器
|
||||
- 避免硬编码测试数据
|
||||
- 使用测试夹具提供的预定义数据
|
||||
|
||||
### 4. 错误处理
|
||||
|
||||
- 在测试用例中使用try-catch捕获错误
|
||||
- 使用测试日志记录错误信息
|
||||
- 在测试失败时截图
|
||||
|
||||
```typescript
|
||||
test('测试用例', async ({ page }) => {
|
||||
try {
|
||||
await page.goto('/pages/calendar/index');
|
||||
expect(await page.title()).toContain('万年历');
|
||||
} catch (error) {
|
||||
await page.screenshot({ path: 'test-failure.png' });
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 5. 等待策略
|
||||
|
||||
- 使用页面对象提供的等待方法
|
||||
- 避免使用固定的等待时间
|
||||
- 使用Playwright的自动等待机制
|
||||
|
||||
```typescript
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('.element', { state: 'visible' });
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 测试失败时的调试
|
||||
|
||||
1. 查看测试日志:控制台输出
|
||||
2. 查看截图:`test-results/uniapp-artifacts/`
|
||||
3. 查看测试报告:`npm run test:e2e:uniapp:report`
|
||||
4. 使用调试模式运行:`npm run test:e2e:uniapp:debug`
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **元素未找到**
|
||||
- 检查选择器是否正确
|
||||
- 确保元素已加载
|
||||
- 使用适当的等待策略
|
||||
|
||||
2. **测试超时**
|
||||
- 增加超时配置
|
||||
- 检查网络请求是否正常
|
||||
- 优化测试等待策略
|
||||
|
||||
3. **应用未启动**
|
||||
- 确保Uniapp应用已启动
|
||||
- 检查端口是否正确
|
||||
- 查看应用日志
|
||||
|
||||
## CI/CD集成
|
||||
|
||||
### GitHub Actions示例
|
||||
|
||||
```yaml
|
||||
name: Uniapp E2E Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
- run: npm ci
|
||||
- run: npm run test:e2e:uniapp
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results/
|
||||
```
|
||||
|
||||
## 扩展开发
|
||||
|
||||
### 添加新的页面对象
|
||||
|
||||
1. 在`pages/`目录下创建新的页面类
|
||||
2. 继承`BasePage`类
|
||||
3. 实现页面特定的方法和选择器
|
||||
|
||||
```typescript
|
||||
import { BasePage } from './base-page';
|
||||
|
||||
export class NewPage extends BasePage {
|
||||
private readonly selectors = {
|
||||
// 页面选择器
|
||||
};
|
||||
|
||||
async navigate() {
|
||||
await this.navigate('/pages/new/index');
|
||||
}
|
||||
|
||||
async doSomething() {
|
||||
// 页面方法
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 添加新的测试用例
|
||||
|
||||
1. 在`e2e/uniapp/`目录下创建新的测试文件
|
||||
2. 使用`test.describe`组织测试用例
|
||||
3. 使用页面对象进行测试
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { NewPage } from './pages/new-page';
|
||||
|
||||
test.describe('新功能测试', () => {
|
||||
test('应该能够执行新功能', async ({ page }) => {
|
||||
const newPage = new NewPage(page);
|
||||
await newPage.navigate();
|
||||
await newPage.doSomething();
|
||||
|
||||
expect(await page.title()).toContain('新页面');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 并行执行
|
||||
|
||||
Playwright默认支持并行执行测试,可以通过配置文件调整:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
workers: 4,
|
||||
fullyParallel: true,
|
||||
});
|
||||
```
|
||||
|
||||
### 测试隔离
|
||||
|
||||
确保每个测试用例都是独立的,避免测试之间的依赖:
|
||||
|
||||
```typescript
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await page.close();
|
||||
});
|
||||
```
|
||||
|
||||
### 重试机制
|
||||
|
||||
配置测试失败时的重试次数:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
retries: 2,
|
||||
});
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
本E2E测试工具提供了完整的Uniapp应用端到端测试解决方案,包括:
|
||||
|
||||
- ✅ 模块化的测试用例编写
|
||||
- ✅ 统一的测试环境配置
|
||||
- ✅ 常用测试操作的封装与复用
|
||||
- ✅ 清晰的测试报告与日志输出
|
||||
- ✅ 页面对象模型(POM)
|
||||
- ✅ 多浏览器支持
|
||||
- ✅ 跨平台兼容性测试
|
||||
- ✅ 自动化测试执行流程
|
||||
- ✅ 详细的测试报告生成
|
||||
|
||||
通过使用本工具,可以高效地编写、执行和维护E2E测试,确保应用的质量和稳定性。
|
||||
Reference in New Issue
Block a user