- 创建完整Playwright测试方案文档(docs/specs/) - 创建Playwright配置文件(tests/playwright.config.ts) - 创建测试数据工具类(tests/e2e/utils/test-data.ts) - 建立测试目录结构:fixtures/pages/specs/utils - 支持CI/CD集成,测试失败阻断发布 - 覆盖登录、门诊医生站、手术计费、Bug回归测试 关联任务: UI功能性测试方案落地
6.8 KiB
6.8 KiB
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 目标
- 核心业务流程自动化覆盖率达到 80%+
- 已修复Bug 100% 回归测试覆盖
- 每次代码推送自动触发测试,失败阻断发布
二、项目结构
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)
# 测试环境配置
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)
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)
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)
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)
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);
});
});
五、执行命令
# 安装浏览器
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脚本
{
"scripts": {
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:report": "playwright show-report"
}
}
6.2 Spug流水线集成
# 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流水线集成 | 赵云+运维 |
八、注意事项
- 测试数据隔离:使用独立的测试数据库,不污染生产数据
- 环境变量:敏感信息通过
.env.test管理,不提交到git - 截图留痕:失败时自动截图,便于排查
- 测试优先:新功能开发时同步编写测试用例