# HIS项目 Playwright E2E 自动化测试方案 v1.0 ## 一、方案概述 ### 1.1 选型理由 - **Playwright** 是微软开源的端到端测试框架,完美适配 Vue 3 + Vite 技术栈 - 自动等待机制适合HIS系统复杂交互场景(异步加载、动态渲染) - 支持多浏览器(Chromium/Firefox/WebKit),CI/CD集成成熟 - 已有 `@playwright/test ^1.58.2` 依赖 installed ### 1.2 目标 1. 核心业务流程自动化覆盖率达到 80%+ 2. 已修复Bug 100% 回归测试覆盖 3. 每次代码推送自动触发测试,失败阻断发布 ## 二、项目结构 ``` openhis-ui-vue3/ ├── tests/ │ ├── e2e/ │ │ ├── fixtures/ # 测试夹具 │ │ │ └── auth.ts # 登录认证fixture │ │ ├── pages/ # 页面对象模型(POM) │ │ │ ├── LoginPage.ts │ │ │ ├── DoctorStationPage.ts │ │ │ └── SurgeryBillingPage.ts │ │ ├── specs/ # 测试用例 │ │ │ ├── login.spec.ts │ │ │ ├── doctor-station.spec.ts │ │ │ ├── surgery-billing.spec.ts │ │ │ └── bug-regression.spec.ts # Bug回归测试 │ │ └── utils/ │ │ └── test-data.ts # 测试数据 │ └── playwright.config.ts # Playwright配置 ├── .env.test # 测试环境变量 └── package.json # 已有playwright依赖 ``` ## 三、环境配置 ### 3.1 环境变量(.env.test) ```bash # 测试环境配置 VITE_APP_BASE_API=http://192.168.110.253:8080 TEST_USERNAME=test_admin TEST_PASSWORD=test123456 TEST_BASE_URL=http://localhost:80 ``` ### 3.2 Playwright配置(playwright.config.ts) ```typescript import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: './tests/e2e/specs', timeout: 60 * 1000, expect: { timeout: 10000 }, fullyParallel: false, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: 1, reporter: [['html', { outputFolder: 'playwright-report' }], ['list']], use: { baseURL: process.env.TEST_BASE_URL || 'http://localhost:80', trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, ], }); ``` ## 四、核心测试用例 ### 4.1 登录测试(login.spec.ts) ```typescript import { test, expect } from '@playwright/test'; test('用户登录成功', async ({ page }) => { await page.goto('/'); await page.fill('input[placeholder="请输入用户名"]', process.env.TEST_USERNAME || 'admin'); await page.fill('input[placeholder="请输入密码"]', process.env.TEST_PASSWORD || '123456'); await page.click('button:has-text("登录")'); await expect(page).toHaveURL(/.*dashboard.*/); await expect(page.locator('.user-avatar')).toBeVisible(); }); test('登录失败-错误密码', async ({ page }) => { await page.goto('/'); await page.fill('input[placeholder="请输入用户名"]', 'admin'); await page.fill('input[placeholder="请输入密码"]', 'wrongpassword'); await page.click('button:has-text("登录")'); await expect(page.locator('.el-message--error')).toBeVisible(); }); ``` ### 4.2 门诊医生站测试(doctor-station.spec.ts) ```typescript import { test, expect } from '@playwright/test'; test.describe('门诊医生站', () => { test.beforeEach(async ({ page }) => { // 登录 await page.goto('/'); await page.fill('input[placeholder="请输入用户名"]', process.env.TEST_USERNAME || 'admin'); await page.fill('input[placeholder="请输入密码"]', process.env.TEST_PASSWORD || '123456'); await page.click('button:has-text("登录")'); await page.waitForURL(/.*dashboard.*/); }); test('#427 检查项目分类手风琴展开', async ({ page }) => { await page.goto('/doctorstation'); // 点击第一个分类 await page.click('.category-item >> nth=0'); await expect(page.locator('.category-content >> nth=0')).toBeVisible(); // 点击第二个分类,第一个应收起 await page.click('.category-item >> nth=1'); await expect(page.locator('.category-content >> nth=0')).not.toBeVisible(); await expect(page.locator('.category-content >> nth=1')).toBeVisible(); }); }); ``` ### 4.3 手术计费回归测试(bug-regression.spec.ts) ```typescript import { test, expect } from '@playwright/test'; test.describe('Bug回归测试', () => { test('#437 手术计费防重复提交', async ({ page }) => { // 登录并导航到手术计费 await page.goto('/'); await page.fill('input[placeholder="请输入用户名"]', process.env.TEST_USERNAME || 'admin'); await page.fill('input[placeholder="请输入密码"]', process.env.TEST_PASSWORD || '123456'); await page.click('button:has-text("登录")'); await page.waitForURL(/.*dashboard.*/); await page.goto('/surgery-billing'); // 快速连续点击新增按钮(测试防重复锁) const addBtn = page.locator('button:has-text("新增")'); await addBtn.click(); await addBtn.click(); // 第二次应被阻止 await addBtn.click(); // 第三次应被阻止 // 验证只弹出一个表单 await expect(page.locator('.el-dialog')).toHaveCount(1); }); }); ``` ## 五、执行命令 ```bash # 安装浏览器 npx playwright install chromium # 运行所有测试 npm run test:e2e # 运行单个测试文件 npx playwright test login.spec.ts # 生成HTML报告 npx playwright show-report # UI模式(调试用) npx playwright test --ui ``` ## 六、CI/CD集成 ### 6.1 package.json脚本 ```json { "scripts": { "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", "test:e2e:report": "playwright show-report" } } ``` ### 6.2 Spug流水线集成 ```yaml # Spug 构建后阶段添加 - name: E2E Testing script: | cd openhis-ui-vue3 npx playwright install --with-deps chromium npm run test:e2e -- --reporter=html # 测试失败则阻断发布 if [ $? -ne 0 ]; then echo "E2E测试失败,阻断发布!" exit 1 fi ``` ## 七、实施计划 | 阶段 | 时间 | 内容 | 负责人 | |------|------|------|--------| | Phase 1 | 第1周 | 登录+核心页面冒烟测试 | 张飞+赵云 | | Phase 2 | 第2-3周 | 门诊医生站+手术计费全流程 | 张飞 | | Phase 3 | 第4周 | Bug回归测试全覆盖 | 张飞 | | Phase 4 | 第5周 | CI/CD流水线集成 | 赵云+运维 | ## 八、注意事项 1. **测试数据隔离**:使用独立的测试数据库,不污染生产数据 2. **环境变量**:敏感信息通过 `.env.test` 管理,不提交到git 3. **截图留痕**:失败时自动截图,便于排查 4. **测试优先**:新功能开发时同步编写测试用例