You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
2 days ago | |
|---|---|---|
| .. | ||
| screenshots | 2 days ago | |
| README.md | 2 days ago | |
| constitution.test.js | 2 days ago | |
| health-profile-complete.test.js | 2 days ago | |
| profile.test.js | 2 days ago | |
README.md
自动化测试文档
本目录包含基于 Playwright 的端到端 (E2E) 自动化测试脚本。
目录结构
tests/
├── README.md # 本文档
├── constitution.test.js # 体质分析功能测试
├── profile.test.js # "我的"页面功能测试
├── health-profile-complete.test.js # 健康档案完整功能测试(推荐)
└── screenshots/ # 测试截图目录
├── constitution-result.png # 体质测试结果截图
├── profile-page.png # 我的页面截图
├── hp-basic-*.png # 基础信息编辑截图
├── hp-lifestyle-*.png # 生活习惯编辑截图
├── hp-medical-*.png # 病史记录添加截图
└── hp-allergy-*.png # 过敏记录添加截图
环境准备
1. 安装依赖
# 安装 Playwright
npm install playwright
# 安装浏览器(首次运行)
npx playwright install chromium
2. 启动应用
测试前需要确保前端和后端服务都在运行:
# 终端1: 启动后端服务
cd server
go run main.go
# 终端2: 启动前端服务
cd app
npm start
# 或
npx expo start --web
确保应用可以通过 http://localhost:8081 访问。
运行测试
运行所有测试
# 从项目根目录运行
node tests/constitution.test.js # 体质分析测试
node tests/profile.test.js # "我的"页面测试
node tests/health-profile-complete.test.js # 健康档案完整测试(推荐)
运行体质分析测试
node tests/constitution.test.js
运行"我的"页面测试
node tests/profile.test.js
运行健康档案完整测试(推荐)
node tests/health-profile-complete.test.js
测试配置
测试脚本中的配置项(位于文件开头):
const APP_URL = "http://localhost:8081"; // 应用地址
const TEST_PHONE = "13800138000"; // 测试手机号
const TEST_CODE = "123456"; // 测试验证码
测试脚本说明
constitution.test.js - 体质分析功能测试
测试流程:
- 登录 - 使用测试账号登录应用
- 导航 - 进入"体质"Tab
- 开始测试 - 点击"开始测试"按钮
- 回答问题 - 自动回答 67 道体质问卷题目
- 提交 - 提交答案获取结果
- 验证结果 - 检查结果页面各元素
- 重新测评 - 测试重新测评功能
验证项目:
| 检查项 | 说明 |
|---|---|
| 登录 | 验证登录流程正常 |
| 导航到体质页面 | 验证 Tab 导航正常 |
| 进入测试页面 | 验证开始测试按钮可点击 |
| 回答所有问题 | 验证 67 道题目全部完成 |
| 提交并查看结果 | 验证提交后跳转到结果页 |
| 体质分析报告标题 | 验证结果页标题显示 |
| 主体质名称 | 验证显示体质类型名称 |
| 体质得分卡片 | 验证得分区域显示 |
| 体质特征卡片 | 验证特征区域显示 |
| 调理建议卡片 | 验证建议区域显示 |
| 咨询 AI 助手按钮 | 验证功能按钮显示 |
| 重新测评按钮 | 验证重新测评按钮显示 |
| 重新测评导航 | 验证重新测评功能正常 |
输出示例:
═══════════════════════════════════════════════════════════
体质分析功能自动化测试
═══════════════════════════════════════════════════════════
打开应用...
【步骤1】检查登录状态...
执行登录流程...
✓ 登录
【步骤2】导航到体质Tab...
✓ 导航到体质页面
【步骤3】开始体质测试...
✓ 进入测试页面
【步骤4】回答问题...
回答第 1/67 题...
回答第 2/67 题...
...
回答第 67/67 题...
所有题目已回答,准备提交...
✓ 回答所有问题: 共 67 题
【步骤5】提交测试...
✓ 提交并查看结果
【步骤6】验证结果页面内容...
✓ 体质分析报告标题
✓ 主体质名称
✓ 体质得分卡片
✓ 体质特征卡片
✓ 调理建议卡片
✓ 咨询AI助手按钮
✓ 重新测评按钮
检测到体质类型: 特禀质
【步骤7】测试重新测评功能...
✓ 重新测评导航
═══════════════════════════════════════════════════════════
测试结果摘要
═══════════════════════════════════════════════════════════
通过: 13 失败: 0
───────────────────────────────────────────────────────────
✓ 登录
✓ 导航到体质页面
✓ 进入测试页面
✓ 回答所有问题 - 共 67 题
✓ 提交并查看结果
✓ 体质分析报告标题
✓ 主体质名称
✓ 体质得分卡片
✓ 体质特征卡片
✓ 调理建议卡片
✓ 咨询AI助手按钮
✓ 重新测评按钮
✓ 重新测评导航
═══════════════════════════════════════════════════════════
profile.test.js - "我的"页面功能测试
测试流程:
- 登录 - 使用测试账号登录
- 导航 - 进入"我的"Tab 页面
- 用户信息显示 - 验证昵称、手机号、编辑按钮
- 编辑昵称 - 打开弹窗、修改昵称、保存
- 适老模式 - 验证开关功能
- 健康管理菜单 - 验证四个菜单项显示
- 健康档案导航 - 跳转到健康档案页面
- 健康档案编辑功能 - 测试基础信息/生活习惯编辑、病史/家族病史/过敏记录新增
- 用药/治疗记录 - 打开弹窗查看
- 关于我们 - 打开弹窗查看
- 退出登录 - 点击并验证确认弹窗
验证项目:
| 检查项 | 说明 |
|---|---|
| 登录 | 使用测试账号登录 |
| 导航到"我的"页面 | Tab 导航正常 |
| 用户昵称显示 | 显示用户昵称 |
| 手机号显示 | 显示手机号 |
| 编辑按钮显示 | 编辑图标可见 |
| 编辑弹窗打开 | 点击编辑打开弹窗 |
| 保存昵称 | 修改昵称并保存成功 |
| 适老模式卡片显示 | 适老模式开关可见 |
| 适老模式开关 | 开关可切换 |
| 健康档案菜单显示 | 健康档案菜单可见 |
| 用药记录菜单显示 | 用药记录菜单可见 |
| 体质报告菜单显示 | 体质报告菜单可见 |
| 对话历史菜单显示 | 对话历史菜单可见 |
| 健康档案页面打开 | 导航到健康档案页 |
| 基础信息卡片显示 | 基础信息卡片可见 |
| 基础信息编辑弹窗打开 | 点击编辑按钮打开弹窗 |
| 生活习惯卡片显示 | 生活习惯卡片可见 |
| 病史记录卡片显示 | 病史记录卡片可见 |
| 病史记录新增弹窗打开 | 点击新增按钮打开弹窗 |
| 家族病史卡片显示 | 家族病史卡片可见 |
| 过敏记录卡片显示 | 过敏记录卡片可见 |
| 用药记录弹窗打开 | 点击打开用药记录弹窗 |
| 退出登录按钮显示 | 退出按钮可见 |
运行命令:
node tests/profile.test.js
health-profile-complete.test.js - 健康档案完整功能测试(推荐)
这是最全面的健康档案测试脚本,覆盖所有可编辑字段的输入和保存验证。
测试范围:
| 功能模块 | 测试字段数 | 测试内容 |
|---|---|---|
| 基础信息 | 9 个字段 | 姓名、性别、出生日期、身高、体重、血型、职业、婚姻状况、地区 |
| 生活习惯 | 10 个字段 | 入睡时间、起床时间、睡眠质量、三餐规律、饮食偏好、日饮水量、运动频率、运动类型、吸烟、饮酒 |
| 病史记录 | 5 个字段 | 疾病名称、疾病类型、诊断日期、治疗状态、备注 |
| 家族病史 | 3 个字段 | 亲属关系、疾病名称、备注 |
| 过敏记录 | 4 个字段 | 过敏类型、过敏原、严重程度、过敏反应描述 |
测试流程:
- 登录 - 使用测试账号登录
- 导航 - 进入健康档案页面
- 基础信息编辑 - 测试所有 9 个字段的输入和保存
- 生活习惯编辑 - 测试所有 10 个字段的输入和保存
- 病史记录添加 - 测试添加新病史记录(5 个字段)
- 家族病史添加 - 测试添加新家族病史(3 个字段)
- 过敏记录添加 - 测试添加新过敏记录(4 个字段)
- 数据验证 - 刷新页面后验证所有数据是否正确保存
验证项目:
| 检查项 | 说明 |
|---|---|
| 导航到健康档案页面 | Tab 和菜单导航正常 |
| 打开基础信息编辑弹窗 | 编辑按钮可点击 |
| 基础信息-姓名输入 | TextInput 输入正常 |
| 基础信息-性别选择 | SegmentedButtons 选择正常 |
| 基础信息-出生日期输入 | 日期格式输入正常 |
| 基础信息-身高/体重输入 | 数字输入正常 |
| 基础信息-血型输入 | 文本输入正常 |
| 基础信息-职业输入 | 文本输入正常 |
| 基础信息-婚姻状况选择 | SegmentedButtons 选择正常 |
| 基础信息-地区输入 | 文本输入正常 |
| 基础信息-保存成功 | API 调用成功,显示提示 |
| 基础信息-保存后数据显示 | 页面正确显示保存的数据 |
| 生活习惯-所有字段测试 | 同上,共 10 个字段 |
| 病史记录-添加新记录 | 弹窗、输入、添加、显示 |
| 家族病史-添加新记录 | 弹窗、输入、添加、显示 |
| 过敏记录-添加新记录 | 弹窗、输入、添加、显示 |
| 刷新后数据验证 | 页面刷新后数据仍然正确 |
输出示例:
═══════════════════════════════════════════════════════════
健康档案完整功能自动化测试
═══════════════════════════════════════════════════════════
测试范围:
- 基础信息: 9个字段(姓名、性别、出生日期、身高、体重、血型、职业、婚姻、地区)
- 生活习惯: 10个字段(入睡时间、起床时间、睡眠质量、三餐规律、饮食偏好、
日饮水量、运动频率、运动类型、吸烟、饮酒)
- 病史记录: 5个字段(疾病名称、疾病类型、诊断日期、治疗状态、备注)
- 家族病史: 3个字段(亲属关系、疾病名称、备注)
- 过敏记录: 4个字段(过敏类型、过敏原、严重程度、过敏反应描述)
【步骤2】测试基础信息编辑(9个字段)...
✓ 打开基础信息编辑弹窗
✓ 基础信息-姓名输入
✓ 基础信息-性别选择
✓ 基础信息-出生日期输入
✓ 基础信息-身高输入
✓ 基础信息-体重输入
✓ 基础信息-血型输入
✓ 基础信息-职业输入
✓ 基础信息-婚姻状况选择
✓ 基础信息-地区输入
✓ 基础信息-保存成功 - 显示保存成功提示
✓ 基础信息-保存后姓名显示
✓ 基础信息-保存后地区显示
✓ 基础信息-保存后职业显示
... (更多测试输出)
═══════════════════════════════════════════════════════════
测试结果摘要
═══════════════════════════════════════════════════════════
通过: 58 失败: 0
═══════════════════════════════════════════════════════════
运行命令:
node tests/health-profile-complete.test.js
编写新测试
基础模板
const { chromium } = require("playwright");
const APP_URL = "http://localhost:8081";
// 测试结果统计
const testResults = { passed: 0, failed: 0, tests: [] };
function logTest(name, passed, detail = "") {
const status = passed ? "✓" : "✗";
console.log(`${status} ${name}${detail ? ": " + detail : ""}`);
testResults.tests.push({ name, passed, detail });
if (passed) testResults.passed++;
else testResults.failed++;
}
async function runTests() {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
// 监听错误
page.on("console", (msg) => {
if (msg.type() === "error") {
console.log("[Console Error]", msg.text());
}
});
page.on("pageerror", (error) => {
console.log("[Page Error]", error.message);
});
try {
await page.goto(APP_URL);
await page.waitForTimeout(2000);
// 添加测试步骤...
} catch (error) {
console.error("测试中断:", error.message);
await page.screenshot({ path: "tests/screenshots/error.png" });
} finally {
// 打印结果
console.log(`\n通过: ${testResults.passed} 失败: ${testResults.failed}`);
await browser.close();
process.exit(testResults.failed > 0 ? 1 : 0);
}
}
runTests();
常用操作
点击元素
// 方式1: 文本定位
await page.locator("text=按钮文字").click();
// 方式2: 角色定位
await page.getByRole("button", { name: "提交" }).click();
// 方式3: 坐标点击 (适用于 React Native Web)
const pos = await page.evaluate(() => {
const el = document.querySelector("text=按钮");
const rect = el.getBoundingClientRect();
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
});
await page.mouse.click(pos.x, pos.y);
// 强制点击 (忽略可见性检查)
await page.locator("text=按钮").click({ force: true });
输入文本
const input = page.locator("input").first();
await input.fill("输入内容");
等待元素
// 等待元素可见
await page.locator("text=内容").waitFor({ state: "visible", timeout: 5000 });
// 检查元素是否可见
const visible = await page
.locator("text=内容")
.isVisible({ timeout: 2000 })
.catch(() => false);
截图
await page.screenshot({ path: "tests/screenshots/截图名.png" });
注意事项
React Native Web 特殊处理
由于 React Native Web 的渲染机制,某些标准选择器可能不起作用:
- 优先使用坐标点击 - 通过
evaluate获取元素位置后用mouse.click - 使用 force 选项 - 某些元素可能被遮挡,使用
{ force: true } - 增加等待时间 - React Native 动画可能需要更长时间完成
测试账号
测试使用的账号:
- 手机号:
13800138000 - 验证码:
123456
截图目录
测试截图保存在 tests/screenshots/ 目录下,包括:
- 测试过程截图
- 错误截图(当测试失败时自动保存)
CI/CD 集成
可以在 CI/CD 流程中使用 headless 模式运行测试:
// 修改 browser launch 配置
const browser = await chromium.launch({
headless: true, // 无头模式
});
退出码说明:
0- 所有测试通过1- 存在测试失败