# E2E测试框架使用文档 ## 目录 - [概述](#概述) - [快速开始](#快速开始) - [项目结构](#项目结构) - [核心功能](#核心功能) - [编写测试](#编写测试) - [运行测试](#运行测试) - [CI/CD集成](#cicd集成) - [最佳实践](#最佳实践) - [故障排查](#故障排查) ## 概述 本E2E测试框架基于Playwright构建,为uniapp和admin模块提供完整的端到端测试解决方案。框架采用模块化设计,支持前后端完全联通的测试场景,确保业务流程的完整性和正确性。 ### 主要特性 - ✅ 基于Playwright的现代化E2E测试框架 - ✅ 支持uniapp和admin模块的全流程业务测试 - ✅ 完整的测试数据管理和清理机制 - ✅ 丰富的测试辅助工具(表单、表格、断言等) - ✅ 详细的测试日志和截图功能 - ✅ 多种测试报告格式(HTML、JSON、JUnit) - ✅ 完整的CI/CD集成支持 - ✅ 支持多浏览器和多设备测试 ## 快速开始 ### 环境要求 - Node.js >= 18.0.0 - npm >= 9.0.0 - Docker(用于运行测试环境) ### 安装依赖 ```bash cd everything-is-suitable-test npm install ``` ### 安装Playwright浏览器 ```bash npm run test:install ``` ### 配置环境变量 复制环境变量示例文件: ```bash cp .env.example .env ``` 编辑`.env`文件,配置测试环境: ```env TEST_ENV=local ADMIN_BASE_URL=http://localhost:5174 UNIAPP_BASE_URL=http://localhost:8081 API_BASE_URL=http://127.0.0.1:8080 TEST_USERNAME=admin TEST_PASSWORD=admin123 MOCK_ENABLED=false TEST_TIMEOUT=30000 ``` ### 运行测试 ```bash npm run test ``` ## 项目结构 ``` everything-is-suitable-test/ ├── e2e/ │ ├── fixtures/ # 测试夹具 │ │ └── test-fixtures.ts # 自定义测试夹具 │ ├── core/ # 核心模块 │ │ ├── test-config.ts # 测试配置管理 │ │ ├── test-logger.ts # 测试日志记录 │ │ ├── test-reporter.ts # 测试报告生成 │ │ └── test-data-manager.ts # 测试数据管理 │ ├── helpers/ # 测试辅助工具 │ │ ├── api-helper.ts # API请求辅助 │ │ ├── form-helper.ts # 表单操作辅助 │ │ ├── table-helper.ts # 表格操作辅助 │ │ ├── screenshot-helper.ts # 截图辅助 │ │ └── assertion-helper.ts # 断言辅助 │ └── examples/ # 示例测试 │ ├── user-management.spec.ts │ ├── api-integration.spec.ts │ ├── uniapp-almanac.spec.ts │ ├── uniapp-user.spec.ts │ ├── admin-user-management.spec.ts │ └── admin-role-management.spec.ts ├── playwright.config.ts # Playwright配置 ├── package.json ├── tsconfig.json └── .env.example ``` ## 核心功能 ### 测试夹具 (Fixtures) 框架提供了一组自定义测试夹具,可以在测试中直接使用: ```typescript test('示例测试', async ({ page, testConfig, testLogger, testDataManager, apiHelper, formHelper, tableHelper, screenshotHelper, assertionHelper }) => { // 使用夹具进行测试 }); ``` #### 可用夹具 | 夹具名称 | 描述 | |---------|------| | `testConfig` | 测试配置管理 | | `testLogger` | 测试日志记录 | | `testReporter` | 测试报告生成 | | `testDataManager` | 测试数据管理 | | `apiHelper` | API请求辅助 | | `formHelper` | 表单操作辅助 | | `tableHelper` | 表格操作辅助 | | `screenshotHelper` | 截图辅助 | | `assertionHelper` | 断言辅助 | ### 测试数据管理 `TestDataManager`提供完整的测试数据生命周期管理: ```typescript const testUser = await testDataManager.createTestUser({ realName: '测试用户', email: 'test@example.com' }); // 测试完成后自动清理 ``` ### 测试辅助工具 #### APIHelper ```typescript await apiHelper.login('admin', 'admin123'); const response = await apiHelper.get('/api/sys/user'); await apiHelper.post('/api/sys/user', userData); await apiHelper.put('/api/sys/user', updateData); await apiHelper.delete(`/api/sys/user/${userId}`); ``` #### FormHelper ```typescript await formHelper.fillField('input[name="username"]', 'testuser'); await formHelper.fillForm({ 'input[name="username"]': { value: 'testuser' }, 'input[name="password"]': { value: 'password123' } }); await formHelper.submitForm('button[type="submit"]'); ``` #### TableHelper ```typescript const rowCount = await tableHelper.getRowCount('.user-table'); const cellText = await tableHelper.getCellText('.user-table', 1, 2); const matchingRows = await tableHelper.findRowsByCellText('.user-table', 'testuser'); await tableHelper.clickRow('.user-table', 1); ``` #### AssertionHelper ```typescript await assertionHelper.assertElementVisible(page, '.user-table'); await assertionHelper.assertElementText(page, '.user-name', '张三'); await assertionHelper.assertSuccessMessage(page); await assertionHelper.assertAPISuccess(response); ``` #### ScreenshotHelper ```typescript await screenshotHelper.takeScreenshot('test-name'); await screenshotHelper.takeElementScreenshot('.element', 'element-name'); await screenshotHelper.takeScreenshotOnFailure('test-name'); await screenshotHelper.takeScreenshotOnSuccess('test-name'); ``` ## 编写测试 ### 基本测试结构 ```typescript import { test, expect } from './fixtures/test-fixtures'; test.describe('功能模块测试', () => { test.beforeEach(async ({ page, testConfig, testLogger }) => { testLogger.startTest('功能模块测试'); await page.goto(testConfig.getEnvironment().baseURL); }); test.afterEach(async ({ testLogger }) => { testLogger.endTest('功能模块测试', 'passed'); }); test('TC-001: 测试用例名称', async ({ page, formHelper, assertionHelper, testLogger, screenshotHelper }) => { testLogger.startStep('步骤1: 描述步骤'); // 测试逻辑 testLogger.endStep('步骤1: 描述步骤', 'passed'); await screenshotHelper.takeScreenshotOnSuccess('test-name'); }); }); ``` ### 测试命名规范 - 测试套件:使用`test.describe()`组织相关测试 - 测试用例:使用`TC-模块-序号: 描述`格式 - 测试步骤:使用`步骤N: 描述`格式 ### 测试最佳实践 1. **使用测试夹具**:充分利用框架提供的夹具,避免重复代码 2. **详细日志**:使用`testLogger`记录测试步骤,便于调试 3. **截图记录**:在关键步骤和测试结束时截图 4. **数据清理**:使用`testDataManager`管理测试数据,自动清理 5. **断言明确**:使用`assertionHelper`进行清晰的断言 6. **等待稳定**:使用`waitFor`等待元素状态稳定 ## 运行测试 ### 本地运行 ```bash # 运行所有测试 npm run test # 运行特定测试文件 npx playwright test e2e/examples/user-management.spec.ts # 运行特定测试用例 npx playwright test -g "TC-USER-001" # 有头模式运行 npm run test:headed # 调试模式 npm run test:debug # UI模式 npm run test:ui ``` ### Docker环境运行 ```bash # 启动测试环境 docker-compose -f docker-compose.test.yml up -d # 等待服务启动 sleep 30 # 运行测试 npm run test # 停止环境 docker-compose -f docker-compose.test.yml down ``` ### 查看测试报告 ```bash # HTML报告 npm run test:report # JSON报告 cat test-results/results.json # JUnit报告 cat test-results/junit.xml ``` ## CI/CD集成 ### Woodpecker CI 测试框架已集成Woodpecker CI,配置文件位于项目根目录的`.woodpecker.yml`。 **触发条件**: - 推送到main或develop分支 - 创建Pull Request - 每天凌晨2点定时执行 **测试流程**: 1. 启动Docker测试环境 2. 并行运行E2E测试(4个分片) 3. 执行API集成测试 4. 生成HTML测试报告 5. 测试失败时发送Slack通知 **Pipeline结构**: - `setup`: 初始化Docker环境 - `e2e-tests`: 执行端到端测试(并行4个分片) - `api-tests`: 执行API集成测试 - `test-report`: 合并测试报告 - `notify-failure`: 测试失败时发送通知 - `nightly-tests`: 每日定时执行完整测试 详细配置说明请参考:[WOODPECKER_CI.md](../WOODPECKER_CI.md) ### 测试报告 测试完成后会生成以下报告: 1. **HTML报告**:交互式HTML报告,包含测试详情和截图 2. **JSON报告**:机器可读的JSON格式报告 3. **JUnit报告**:兼容JUnit的XML格式报告 报告位置: - `playwright-report/`:HTML报告 - `test-results/results.json`:JSON报告 - `test-results/junit.xml`:JUnit报告 ## 最佳实践 ### 1. 测试设计原则 - **测试金字塔**:70% API测试,20% 集成测试,10% E2E测试 - **独立性**:每个测试用例应该独立运行,不依赖其他测试 - **可重复性**:测试结果应该稳定可重复 - **快速反馈**:优先测试核心业务流程 ### 2. 数据管理 - 使用`TestDataManager`创建和管理测试数据 - 测试完成后自动清理测试数据 - 避免硬编码测试数据,使用工厂模式生成 ### 3. 错误处理 - 使用`try-catch`捕获预期异常 - 提供清晰的错误信息 - 失败时自动截图和记录日志 ### 4. 性能优化 - 合理使用并行执行 - 避免不必要的等待 - 复用浏览器实例 ### 5. 维护性 - 遵循代码规范 - 添加必要的注释 - 定期重构测试代码 - 更新测试文档 ## 故障排查 ### 常见问题 #### 1. 测试超时 **问题**:测试执行超时 **解决方案**: ```typescript // 增加超时时间 test.setTimeout(60000); // 或在配置中设置 use: { actionTimeout: 60000, navigationTimeout: 60000 } ``` #### 2. 元素未找到 **问题**:无法定位页面元素 **解决方案**: ```typescript // 等待元素可见 await page.waitForSelector('.element', { timeout: 10000 }); // 使用更精确的选择器 await page.locator('.container .element').click(); ``` #### 3. 测试数据冲突 **问题**:测试数据相互干扰 **解决方案**: ```typescript // 使用唯一标识符 const timestamp = Date.now(); const username = `test_user_${timestamp}`; // 每个测试使用独立数据 beforeEach(async () => { testUser = await testDataManager.createTestUser(); }); afterEach(async () => { await testDataManager.cleanup(); }); ``` #### 4. 环境配置问题 **问题**:无法连接到测试环境 **解决方案**: ```bash # 检查环境变量 cat .env # 验证服务状态 docker-compose ps # 查看服务日志 docker-compose logs backend ``` ### 调试技巧 #### 1. 使用调试模式 ```bash npm run test:debug ``` #### 2. 使用UI模式 ```bash npm run test:ui ``` #### 3. 查看详细日志 ```typescript testLogger.debug('调试信息'); testLogger.info('一般信息'); testLogger.warn('警告信息'); testLogger.error('错误信息', error); ``` #### 4. 截图和录屏 ```typescript // 失败时自动截图 await screenshotHelper.takeScreenshotOnFailure('test-name'); // 手动截图 await screenshotHelper.takeScreenshot('debug-point'); // 录屏(在playwright.config.ts中配置) use: { video: 'retain-on-failure' } ``` ### 性能优化 #### 1. 减少测试时间 ```typescript // 并行执行测试 workers: 4 // 跳过慢速测试 test.skip('慢速测试', async () => {}); // 使用项目分组 projects: [ { name: 'fast', testMatch: '**/*.fast.spec.ts' }, { name: 'slow', testMatch: '**/*.slow.spec.ts' } ] ``` #### 2. 优化等待时间 ```typescript // 使用智能等待 await page.waitForSelector('.element', { state: 'visible' }); // 避免固定等待 // 不推荐:await page.waitForTimeout(5000); // 推荐:await page.waitForLoadState('networkidle'); ``` ## 贡献指南 ### 添加新测试 1. 在`e2e/examples/`目录下创建新的测试文件 2. 遵循测试命名规范 3. 使用测试夹具和辅助工具 4. 添加详细的测试步骤和日志 5. 提交前运行测试确保通过 ### 扩展框架 1. 在`e2e/helpers/`目录下添加新的辅助工具 2. 在`e2e/fixtures/test-fixtures.ts`中注册新的夹具 3. 更新文档说明新功能 4. 添加示例测试 ## 许可证 MIT License ## 联系方式 如有问题或建议,请联系测试团队。