|
|
@@ -1,339 +1,663 @@
|
|
|
-# 数字能量小程序测试清单
|
|
|
+# 数字心理学AI智能体 — 测试用例全集 v3.0
|
|
|
|
|
|
-> 所属角色: `shu-zi-neng-liang-test-engineer`
|
|
|
-> 基于: phase1-product-plan.md, phase1-user-stories.md, system-spec.md
|
|
|
-> 版本: v1.0
|
|
|
+> 所属角色: `test-engineer`
|
|
|
+> 基于: `phase1-product-plan.md`, `phase1-user-stories.md`, `system-spec.md`, 实际代码实现(Java Spring Boot + UniApp)
|
|
|
+> 版本: v3.0
|
|
|
+> 覆盖范围: Phase 1 全部 8 个 EPIC(含 P0/P1/P2)
|
|
|
+> 总用例数: ~290+
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 模块清单
|
|
|
-
|
|
|
-| 模块 | 文件/组件 | 优先级 |
|
|
|
-|------|-----------|--------|
|
|
|
-| 首页输入 | index.js + index.wxml + index.wxss | P0 |
|
|
|
-| 三角形命盘 | chart.js + chart.wxml + chart.wxss + triangle组件 | P0 |
|
|
|
-| AI解读 | reading.js + reading.wxml + reading.wxss | P0 |
|
|
|
-| 付费订阅 | subscribe.js + subscribe.wxml + subscribe.wxss | P0 |
|
|
|
-| 个人中心 | profile.js + profile.wxml + profile.wxss | P1 |
|
|
|
-| 分销面板 | distribution.js + distribution.wxml + distribution.wxss | P1 |
|
|
|
-| 计算引擎 | calculator.js | P0 |
|
|
|
-| App全局 | app.js + app.wxss + app.json | P1 |
|
|
|
-| 云函数: 用户注册 | registerUser/index.js | P1 |
|
|
|
-| 云函数: 会话检查 | checkSession/index.js | P1 |
|
|
|
-| 云函数: AI解读 | generateReading/index.js | P0 |
|
|
|
-| 云函数: 支付创建 | createPayment/index.js | P0 |
|
|
|
-| 云函数: 佣金查询 | getCommission/index.js | P1 |
|
|
|
-| 云函数: 提现申请 | applyWithdraw/index.js | P1 |
|
|
|
-| 云函数: 二维码 | getQRCode/index.js | P1 |
|
|
|
-| 云函数: 上级查询 | getReferrerInfo/index.js | P1 |
|
|
|
-| 云函数: 支付回调 | paymentCallback/index.js | P0 |
|
|
|
+## 一、测试策略
|
|
|
|
|
|
----
|
|
|
+### 1.1 测试分层
|
|
|
|
|
|
-## 测试用例清单
|
|
|
-
|
|
|
-### TC-01: 计算引擎 (P0)
|
|
|
-
|
|
|
-| # | 用例 | 输入 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 1.1 | 个位数原样返回 | reduceToDigit(5) | 5 |
|
|
|
-| 1.2 | 两位数归约 | reduceToDigit(10) | 1 |
|
|
|
-| 1.3 | 多位数归约 | reduceToDigit(99) | 9 |
|
|
|
-| 1.4 | 多位数归约链 | reduceToDigit(999) | 9 |
|
|
|
-| 1.5 | 卓越数11保留 | reduceToDigit(11) | 11 |
|
|
|
-| 1.6 | 卓越数22保留 | reduceToDigit(22) | 22 |
|
|
|
-| 1.7 | 卓越数33保留 | reduceToDigit(33) | 33 |
|
|
|
-| 1.8 | 完整命盘-已知日期 | calculateTriangle(1990, 1, 1) | 手算验真15个位置 |
|
|
|
-| 1.9 | 完整命盘-月份两位数 | calculateTriangle(1985, 12, 25) | D=3, E=7 |
|
|
|
-| 1.10 | 完整命盘-日两位数 | calculateTriangle(2000, 6, 15) | D=6, E=6 |
|
|
|
-| 1.11 | 完整命盘-年份奇数 | calculateTriangle(2001, 3, 8) | A=2, B=0, C=1 |
|
|
|
-| 1.12 | 主性格卓越数 | calculateTriangle(1994, 5, 12) | O 可能是22/33 |
|
|
|
-| 1.13 | 五区sum值 | 各场景 | sum=reduceToDigit(各位置值和) |
|
|
|
-| 1.14 | 数字含义1-9完整 | 1-9 | 均有title和trait |
|
|
|
-| 1.15 | 卓越数字含义 | 11, 22, 33 | 有特殊含义 |
|
|
|
-
|
|
|
-### TC-02: 页面交互与状态 (P0)
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 2.1 | 未登录用户可输入 | 打开首页,填写日期 | 可操作,不强制登录 |
|
|
|
-| 2.2 | 推广链接打开 | URL带?ref=ABC123 | 底部显示分享者信息,缓存推广码 |
|
|
|
-| 2.3 | 免费用户3次限制 | 连续生成4次命盘 | 第4次弹出"次数已用完"引导订阅 |
|
|
|
-| 2.4 | 能量师无限生成 | 能量师身份不限次 | 不会触发次数限制 |
|
|
|
-| 2.5 | 跨午夜重置 | 00:00后检查 | 免费配额重置为0/3 |
|
|
|
-| 2.6 | 无效日期输入 | 月份=13, 日期=32 | 显示验证错误提示 |
|
|
|
-| 2.7 | 空字段提交 | 不选择年月日直接点生成 | 提示"请填写完整的出生日期" |
|
|
|
-| 2.8 | chart页历史id查找 | 点击历史记录中的命盘 | 正确加载对应命盘数据 |
|
|
|
-| 2.9 | chart页无效id | URL手动修改为不存在id | 显示空状态/错误提示 |
|
|
|
-| 2.10 | 免费用户解读限制 | 免费用户查看AI解读 | 仅显示主性格概要 |
|
|
|
-| 2.11 | 能量师完整解读 | 能量师查看AI解读 | 显示主性格+五区完整内容 |
|
|
|
-| 2.12 | 解读缓存 | 两次进入同一命盘解读页 | 第二次不调用云函数,使用本地缓存 |
|
|
|
-| 2.13 | 解读加载状态 | 首次进入解读页 | 显示骨架屏/loading动画 |
|
|
|
-| 2.14 | 解读内容折叠展开 | 点击章节标题 | 正确折叠/展开内容卡片 |
|
|
|
-| 2.15 | 免责声明存在 | 解读页底部 | 显示"本解读由AI生成,仅供参考" |
|
|
|
-
|
|
|
-### TC-03: Canvas可视化 (P0)
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 3.1 | 五层十五格绘制 | 生成命盘 → chart页 | 5层15个数字卡片完整绘制 |
|
|
|
-| 3.2 | 连接线 | 检查线条 | 底层→顶层所有连接线正确 |
|
|
|
-| 3.3 | 数字颜色 | 1-9每个数字 | 颜色与DIGIT_COLORS配置一致 |
|
|
|
-| 3.4 | 卓越数高亮 | 主性格=11/22/33 | 金底+星标+边框加粗 |
|
|
|
-| 3.5 | 位置标签 | 每个数字下方 | 显示getPositionName的对应名称 |
|
|
|
-| 3.6 | 点击交互 | 点击数字卡片 | 弹出含义面板(title+trait+position) |
|
|
|
-| 3.7 | 区域背景色 | 五区 | 使用ZONE_COLORS颜色区分 |
|
|
|
-| 3.8 | 姓名生日显示 | 命盘上方 | 显示姓名和出生日期 |
|
|
|
-| 3.9 | 320px宽屏幕 | iPhone SE | 不溢出,数字不重叠 |
|
|
|
-| 3.10 | 414px宽屏幕 | iPhone Plus | 布局适配 |
|
|
|
-| 3.11 | 2x倍屏 | devicePixelRatio=2 | 渲染清晰无锯齿 |
|
|
|
-| 3.12 | 3x倍屏 | devicePixelRatio=3 | 渲染清晰无锯齿 |
|
|
|
-
|
|
|
-### TC-04: 云函数 - generateReading (P0)
|
|
|
-
|
|
|
-| # | 用例 | 输入 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 4.1 | 正常请求 | 完整chartData + name | code=0, 6段解读字符串非空 |
|
|
|
-| 4.2 | 缺少positions | {} | code=400, error="缺少命盘数据" |
|
|
|
-| 4.3 | LLM超时 | 模拟超时 | 触发_fallbackReading降级解读 |
|
|
|
-| 4.4 | LLM返回非JSON | 非法响应 | code=0, mainCharacter=原始文本 |
|
|
|
-| 4.5 | LLM返回JSON in markdown | ```json ... ``` | 正确解析JSON内容 |
|
|
|
-| 4.6 | 缓存读取 | 第二次请求同命盘 | 不走云函数,从本地存储读取 |
|
|
|
-
|
|
|
-### TC-05: 支付订阅 (P0)
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 5.1 | 未登录跳转支付 | 未登录用户点击订阅 | 引导登录或正常跳转 |
|
|
|
-| 5.2 | 支付loading | 点击"立即开通" | 按钮变为loading状态,不可重复点击 |
|
|
|
-| 5.3 | 支付成功 | 模拟支付成功回调 | role→practitioner, expireAt→+1年 |
|
|
|
-| 5.4 | 支付后推广码 | 支付成功后的checkSession | referralCode非空(6位) |
|
|
|
-| 5.5 | 支付取消 | 用户取消支付 | 停留在当前页,角色不变 |
|
|
|
-| 5.6 | 支付失败 | 模拟支付失败 | 显示"支付失败,请重试" |
|
|
|
-| 5.7 | 功能对比表 | 订阅页内容 | 正确展示免费vs能量师差异 |
|
|
|
-| 5.8 | 价格显示 | 订阅页 | ¥398/年,¥1.09/天正确 |
|
|
|
-
|
|
|
-### TC-06: 分销链路 (P1)
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 6.1 | 推广码自动生成 | 支付成功后 | 6位字母+数字唯一码 |
|
|
|
-| 6.2 | 推广码持久化 | 重新登录 | 推广码不变 |
|
|
|
-| 6.3 | 分享卡片携带ref | 能量师分享 | path包含?ref=CODE |
|
|
|
-| 6.4 | 推广链接打开参数 | onLoad(options) | 正确读取ref并缓存 |
|
|
|
-| 6.5 | 注册时绑定上级 | 新用户带ref注册 | invitedBy=上级openid |
|
|
|
-| 6.6 | 上级统计更新 | 新用户注册 | directCount+1 |
|
|
|
-| 6.7 | 关系终身锁定 | 第二次通过他人链接注册 | 不覆盖原有invitedBy |
|
|
|
-| 6.8 | 自邀请不绑定 | 自己扫自己的码 | invitedBy为空 |
|
|
|
-| 6.9 | 一级佣金结算 | 下级付费¥398 | 佣金=¥119.4, status=available |
|
|
|
-| 6.10 | 二级佣金结算 | 下级的下级付费 | 佣金=¥39.8, status=available |
|
|
|
-| 6.11 | 佣金取值精确 | 浮动计算 | 两位小数精确 |
|
|
|
-| 6.12 | 佣金状态流转 | pending→available→completed | 按业务规则流转 |
|
|
|
-| 6.13 | 提现条件验证 | 可提现金额<¥100 | "申请提现"不可点击 |
|
|
|
-| 6.14 | 提现申请提交 | 金额合法 | 记录创建status=pending |
|
|
|
-| 6.15 | 提全额按钮 | 点击"全部提现" | 输入框填充可提现金额 |
|
|
|
-| 6.16 | 超额提现拦截 | 输入>可提现 | 提示"超出可提现金额" |
|
|
|
-
|
|
|
-### TC-07: 用户体系与历史记录 (P1)
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 7.1 | 微信登录 | 点击微信登录 | 获取用户信息,创建/查询用户 |
|
|
|
-| 7.2 | 重复登录 | 同一用户再次登录 | 返回isNew=false |
|
|
|
-| 7.3 | 登录后状态持久化 | 关闭重开小程序 | token有效时自动登录 |
|
|
|
-| 7.4 | 会话过期 | token无效 | 自动跳转为未登录状态 |
|
|
|
-| 7.5 | 历史列表显示 | 个人中心页 | 按时间倒序,显示姓名/生日/主性格 |
|
|
|
-| 7.6 | 历史点击跳转 | 点击历史记录 | 跳转到对应chart页 |
|
|
|
-| 7.7 | 免费用户7天限制 | 8天前的记录 | 不显示 |
|
|
|
-| 7.8 | 能量师全部历史 | 所有记录 | 全部显示 |
|
|
|
-| 7.9 | 历史记录超100条 | 生成101+命盘 | 仅保留最近100条 |
|
|
|
-| 7.10 | 订阅状态显示 | 个人中心 | 能量师显示"已开通"+到期日 |
|
|
|
-
|
|
|
-### TC-08: 边界与异常 (P0/P1)
|
|
|
-
|
|
|
-| # | 用例 | 预期结果 |
|
|
|
-|---|------|---------|
|
|
|
-| 8.1 | 年月日全部为空 | 提示填写完整日期 |
|
|
|
-| 8.2 | 年份=1899 | 日期选择器不可选 |
|
|
|
-| 8.3 | 年份=2100 | 不可选(超过当前年份) |
|
|
|
-| 8.4 | 月份=0 | picker限制不可选 |
|
|
|
-| 8.5 | 月份=13 | picker限制不可选 |
|
|
|
-| 8.6 | 日期=0 | picker限制不可选 |
|
|
|
-| 8.7 | 日期=32 | picker限制不可选 |
|
|
|
-| 8.8 | 闰年2/29 | 合法输入,正常计算 |
|
|
|
-| 8.9 | 非闰年2/29 | picker不可选 |
|
|
|
-| 8.10 | 姓名20字符 | 截断处理 |
|
|
|
-| 8.11 | 姓名全空格 | 显示"未知" |
|
|
|
-| 8.12 | 姓名特殊字符 | 正常显示 |
|
|
|
-| 8.13 | 命盘id含特殊字符 | 能正确查找 |
|
|
|
-| 8.14 | 弱网场景(3G模拟) | 云函数超时能有降级UI |
|
|
|
-| 8.15 | 断网场景 | 提示网络错误,不崩溃 |
|
|
|
-| 8.16 | 存储空间满 | 存储失败时的降级 |
|
|
|
-
|
|
|
-### TC-09: 合规检查 (P0)
|
|
|
-
|
|
|
-| # | 检查项 | 通过标准 |
|
|
|
-|---|--------|---------|
|
|
|
-| 9.1 | 首页文案 | 不含"算命、占卜、预测、占星" |
|
|
|
-| 9.2 | AI解读免责声明 | 末尾包含"本解读由AI生成,仅供参考" |
|
|
|
-| 9.3 | 用户协议链接 | 可点击,打开的页面有效 |
|
|
|
-| 9.4 | 隐私政策链接 | 可点击,打开的页面有效 |
|
|
|
-| 9.5 | 不得收集敏感信息 | 无身份证/银行卡输入 |
|
|
|
-| 9.6 | 支付合规 | 微信支付规范无违规文案 |
|
|
|
-| 9.7 | 分销合规 | 两级分销,无团队计酬,无入门费 |
|
|
|
+| 层 | 范围 | 方法 | 工具 |
|
|
|
+|----|------|------|------|
|
|
|
+| **单元测试** | 计算引擎 calculator.js + CalculatorService.java | 纯函数,输入→输出比对 | Jest / JUnit 5 |
|
|
|
+| **组件测试** | TriangleChart 组件渲染、AI对话交互 | UI 组件渲染 + 交互 | Vitest + happy-dom |
|
|
|
+| **集成测试** | Controller 层 35+ 端点 | HTTP 请求→响应验证 | MockMvc / Postman |
|
|
|
+| **集成测试** | Service 层(UserService/OrderService/CommissionService) | 模拟 Repository 验证业务逻辑 | JUnit + Mockito |
|
|
|
+| **E2E** | 核心用户路径 | 真机+模拟器全链路 | Playwright / 手动 |
|
|
|
+| **探索测试** | 边界/异常/竞态 | 破坏性思维设计测试用例 | 手动 |
|
|
|
|
|
|
----
|
|
|
+### 1.2 严重等级定义
|
|
|
+
|
|
|
+| 等级 | 定义 | 响应要求 |
|
|
|
+|------|------|---------|
|
|
|
+| **S0-Critical** | 核心链路阻塞(无法生成命盘/支付/AI对话/注册登录) | 立即阻塞发布 |
|
|
|
+| **S1-Major** | 功能严重异常(计算错误/状态错乱/佣金算错/数据丢失/权限越界) | 24h内修复 |
|
|
|
+| **S2-Minor** | 功能可用但体验缺陷(UI错位/文案错误/降级文案不佳) | 下一迭代 |
|
|
|
+| **S3-Trivial** | 视觉/文案微调建议 | 积攒修复 |
|
|
|
|
|
|
-## 测试环境要求
|
|
|
+### 1.3 测试环境
|
|
|
|
|
|
| 项目 | 配置 |
|
|
|
|------|------|
|
|
|
-| 微信基础库 | 3.7.1+ |
|
|
|
-| iOS | iPhone 13/14/15, iOS 16+ |
|
|
|
-| Android | 华为/小米/OPPO, Android 12+ |
|
|
|
+| 小程序基础库 | 3.7.1+ |
|
|
|
+| iOS | iPhone 13/14/15/SE, iOS 16+ |
|
|
|
+| Android | 华为Mate/P系列、小米数字系列、OPPO Reno, Android 12+ |
|
|
|
| 微信版本 | 8.0+ |
|
|
|
-| 云开发环境 | test/dev独立环境(非production) |
|
|
|
-| 测试账号 | 至少3个:普通用户A、能量师B、普通用户C(从B邀请注册) |
|
|
|
-
|
|
|
-### TC-10: 分享与导出 (P0) — 新增
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 10.1 | 分享按钮位置 | 命盘展示页底部 | "分享图片"按钮存在 |
|
|
|
-| 10.2 | 免费用户分享限制 | 免费用户每日分享第2次 | 弹出"分享次数已用完"引导订阅 |
|
|
|
-| 10.3 | 分享卡片内容 | 成功分享后 | 卡片包含命盘图+姓名+生日(视觉验证) |
|
|
|
-| 10.4 | 分享到多途径 | 点击分享 | 支持保存到相册/分享好友/分享朋友圈 |
|
|
|
-| 10.5 | PDF导出按钮可见性 | 能量师身份 | 能量师看到"导出PDF"按钮 |
|
|
|
-| 10.6 | PDF导出按钮隐藏 | 普通用户 | 不显示"导出PDF" |
|
|
|
-| 10.7 | PDF功能状态 | 点击PDF导出 | 当前显示"功能开发中",Phase1不做崩溃 |
|
|
|
-| 10.8 | "查看AI解读"按钮 | chart页底部 | 按钮存在可点击 |
|
|
|
-| 10.9 | 能量师分享带ref | 能量师分享chart页 | 分享路径包含?ref=推广码 |
|
|
|
-
|
|
|
-### TC-11: 云函数完整覆盖 (P0/P1) — 新增
|
|
|
-
|
|
|
-**注意:以下测试需云函数部署后执行**
|
|
|
-
|
|
|
-| # | 用例 | 输入 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 11.1 | registerUser:新用户无推广 | 空referrerCode | 创建用户,invitedBy=null |
|
|
|
-| 11.2 | registerUser:已存在用户 | 重复openid | code=0, isNew=false, 不做任何变更 |
|
|
|
-| 11.3 | registerUser:无效推广码 | 不存在的referralCode | 创建用户,invitedBy=null |
|
|
|
-| 11.4 | checkSession:用户不存在 | 未注册openid | isValid=false |
|
|
|
-| 11.5 | checkSession:用户已过期 | practitionerExpireAt<now | role=regular, expireAt返回 |
|
|
|
-| 11.6 | checkSession:有效能量师 | practitionerExpireAt>now | role=practitioner, 返回referralCode |
|
|
|
-| 11.7 | generateReading:name为空 | 无name | 正常返回,名称显示"用户" |
|
|
|
-| 11.8 | paymentCallback:重复回调 | 同outTradeNo二次调用 | 返回"订单已处理"不重复处理 |
|
|
|
-| 11.9 | paymentCallback:上级不是能量师 | invitedBy存在但非能量师 | 跳过一级佣金结算 |
|
|
|
-| 11.10 | paymentCallback:上上级不存在 | parent无invitedBy | 无一级佣金则跳过二级 |
|
|
|
-| 11.11 | paymentCallback:上上级非能量师 | grandparent已过期 | 跳过二级佣金 |
|
|
|
-| 11.12 | applyWithdraw:金额<=0 | amount=0 | code=400, error="无效金额" |
|
|
|
-| 11.13 | applyWithdraw:用户不存在 | 未注册openid | code=401, error="用户不存在" |
|
|
|
-| 11.14 | applyWithdraw:余额不足 | amount>availableTotal | code=400, error="可提现金额不足" |
|
|
|
-| 11.15 | applyWithdraw:低于最低提现 | amount=5000(¥50) | code=400, error="未达到最低提现金额" |
|
|
|
-| 11.16 | applyWithdraw:成功提现 | amount>=10000 | 佣金状态→processing, 创建withdraw记录 |
|
|
|
-| 11.17 | getCommission:空数据 | 无佣金记录 | 返回0值+空数组 |
|
|
|
-| 11.18 | getQRCode:缺少推广码 | 无referralCode | code=400, error="缺少推广码" |
|
|
|
-| 11.19 | getQRCode:上传失败 | 模拟云存储故障 | code=500, 上层降级 |
|
|
|
-| 11.20 | getReferrerInfo:推广码不存在 | 无效码 | found=false |
|
|
|
-
|
|
|
-### TC-12: 代码级边界和异常 (P0) — 新增
|
|
|
-
|
|
|
-| # | 用例 | 验证点 | 预期结果 |
|
|
|
-|---|-------|--------|---------|
|
|
|
-| 12.1 | app.js:cloud.init配置缺失 | 云环境ID未配置时的行为 | 不崩溃,显示友好错误 |
|
|
|
-| 12.2 | app.js:token存在但会话过期 | checkSession返回isValid=false | 调用clearSession,清除本地token |
|
|
|
-| 12.3 | app.js:能量师已过期 | practitionerExpireAt已过 | isPractitioner=false, 功能限制恢复 |
|
|
|
-| 12.4 | app.js:quota_XX存储异常 | localStorage写入失败 | 降级,不阻塞核心功能 |
|
|
|
-| 12.5 | index.js:命盘生成catch | 计算引擎异常(罕见) | showToast"生成失败,请检查日期" |
|
|
|
-| 12.6 | index.js:历史存储满100条 | 第101条生成时 | 最旧记录被移除,保持≤100 |
|
|
|
-| 12.7 | chart.js:订阅状态轮询 | setInterval未clear | onUnload时clearInterval释放 |
|
|
|
-| 12.8 | chart.js:分享时网络中断 | 网络不通点分享 | 不阻塞,降级提示 |
|
|
|
-| 12.9 | reading.js:云函数返回null | generateReading返回reading=null | 显示"解读生成中,请稍后再试" |
|
|
|
-| 12.10 | reading.js:解读全空字段 | LLM返回空字符串 | 各section显示空/兜底文案 |
|
|
|
-| 12.11 | subscribe.js:支付重入 | 连续快速点击支付按钮 | payLoading=true阻止第二次 |
|
|
|
-| 12.12 | subscribe.js:支付后_refreshUser失败 | checkSession云函数异常 | 静默降级,下次onShow时刷新 |
|
|
|
-| 12.13 | profile.js:退出登录后状态 | 退出→重新进入个人中心 | 显示未登录状态 |
|
|
|
-| 12.14 | profile.js:history过滤边界 | 恰好8天前的记录 | 免费用户不显示 |
|
|
|
-| 12.15 | distribution.js:佣金数据加载失败 | getCommission云函数失败 | showToast"加载数据失败",不白屏 |
|
|
|
-| 12.16 | distribution.js:提现金额=0 | 输入0并提交 | showToast"请输入有效金额" |
|
|
|
-| 12.17 | triangle.js:chartData为null | 组件未收到数据 | 不渲染,不崩溃 |
|
|
|
-| 12.18 | triangle.js:Canvas节点不存在 | select失败 | return,不继续执行 |
|
|
|
-| 12.19 | triangle.js:点击canvas超出范围 | 点在三角形外侧 | 不触发select事件 |
|
|
|
-
|
|
|
-### TC-13: 页面入口与引导 (P0) — 新增
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 13.1 | 首页升级引导 | 未付费用户首页 | 显示"开通能量师"按钮/引导 |
|
|
|
-| 13.2 | 命盘页升级引导 | 未付费用户chart页 | 显示"开通能量师 ¥398/年"按钮 |
|
|
|
-| 13.3 | 解读页升级引导 | 未付费用户reading页 | 显示"五区深度解读已锁定"引导卡片 |
|
|
|
-| 13.4 | 分享升级引导 | 免费用户分享次数用完 | 引导到订阅页 |
|
|
|
-| 13.5 | 到期降级后功能 | 过期后进入个人中心 | 分销面板关闭,功能降为普通用户 |
|
|
|
-| 13.6 | 续费操作 | 到期前点击续费 | 跳转订阅页,与原流程一致 |
|
|
|
-| 13.7 | 免费用户每日解读次数用完 | 第2次点击解读 | 弹窗引导订阅或次数限制提示 |
|
|
|
-
|
|
|
-### TC-14: 分销链路上级资格校验 (P0) — 新增
|
|
|
-
|
|
|
-| # | 用例 | 步骤 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 14.1 | 上级已过期不结算 | parent过期+下级付费 | 跳过一级佣金,记录不存在 |
|
|
|
-| 14.2 | 上上级已过期不结算 | grandparent过期+下级付费 | 跳过二级佣金 |
|
|
|
-| 14.3 | 上级是普通用户不结算 | parent非能量师 | 跳过佣金 |
|
|
|
-| 14.4 | 提现后佣金状态 | 提现申请成功 | 对应佣金标记processing |
|
|
|
-| 14.5 | 提现处理完成 | 平台审核 | 佣金状态→completed |
|
|
|
-| 14.6 | 退款时佣金未提现 | 订单退款+佣金available | 佣金→cancelled |
|
|
|
-| 14.7 | 退款时佣金已提现 | 订单退款+佣金已提现 | 从后续佣金抵扣 |
|
|
|
-
|
|
|
-### TC-15: 性能与兼容性 (P0/P1) — 新增
|
|
|
-
|
|
|
-| # | 用例 | 方法 | 预期结果 |
|
|
|
-|---|------|------|---------|
|
|
|
-| 15.1 | 命盘生成<3秒 | console.time计时 | 从点击到页面跳转<3000ms |
|
|
|
-| 15.2 | AI解读加载<5秒 | 云函数调用计时 | 从点击到内容展示<5000ms |
|
|
|
-| 15.3 | Canvas渲染性能 | 连续生成10次命盘 | 无内存泄漏,无卡顿 |
|
|
|
-| 15.4 | 历史记录100条加载 | 快速滚动列表 | 无白屏/闪烁 |
|
|
|
-| 15.5 | 云函数冷启动 | 间隔>5分钟后调用 | 响应<5秒(含冷启动时间) |
|
|
|
-| 15.6 | 图片资源加载 | 小程序首页加载 | 无图片加载失败 |
|
|
|
-| 15.7 | 多个云函数并发 | 同时调用commission+reading | 互不影响,各自返回 |
|
|
|
-| 15.8 | iOS真机渲染 | iPhone 13/14/15 | Canvas与模拟器一致 |
|
|
|
-
|
|
|
-### TC-16: 合规与安全 (P0) — 新增
|
|
|
-
|
|
|
-| # | 检查项 | 通过标准 |
|
|
|
-|---|--------|---------|
|
|
|
-| 16.1 | AppID未硬编码 | project.config.json使用YOUR_APPID_HERE占位 |
|
|
|
-| 16.2 | 云环境ID未硬编码 | 代码中使用YOUR_CLOUD_ENV_ID占位 |
|
|
|
-| 16.3 | LLM API Key不暴露前端 | 仅在云函数环境变量中配置 |
|
|
|
-| 16.4 | 支付SubMchId占位 | 使用YOUR_SUB_MCH_ID |
|
|
|
-| 16.5 | 用户数据删除 | 个人中心有退出登录选项 |
|
|
|
-| 16.6 | 文案合规 | 无"算命、占卜、预测、占星"等敏感词 |
|
|
|
-| 16.7 | 分销合规文案 | 无"团队计酬、入门费"等传销提示 |
|
|
|
-| 16.8 | 支付页面合规 | 无诱导消费、虚假倒计时 |
|
|
|
-
|
|
|
-## 覆盖度总结
|
|
|
-
|
|
|
-| 模块 | 原用例数 | 新增用例数 | 总用例数 | 覆盖率 |
|
|
|
-|------|---------|-----------|---------|--------|
|
|
|
-| 计算引擎 | 15 | 0 | 15 | 100% |
|
|
|
-| 页面交互与状态 | 15 | +7(TC-13) | 22 | 100% |
|
|
|
-| Canvas可视化 | 12 | +3(TC-12.17-19) | 15 | 100% |
|
|
|
-| 云函数generateReading | 6 | +1(TC-11.7) | 7 | 100% |
|
|
|
-| 支付订阅 | 8 | +6(TC-13.1-6) | 14 | 100% |
|
|
|
-| 分销链路 | 16 | +7(TC-14) | 23 | 100% |
|
|
|
-| 用户体系与历史 | 10 | 0 | 10 | 100% |
|
|
|
-| 边界与异常 | 16 | +16(TC-12) | 32 | 100% |
|
|
|
-| 合规检查 | 7 | +8(TC-16) | 15 | 100% |
|
|
|
-| 分享与导出 | 0 | +9(TC-10) | 9 | 100% |
|
|
|
-| 云函数完整覆盖 | 0 | +20(TC-11) | 20 | 100% |
|
|
|
-| 分销上级资格 | 0 | +7(TC-14) | 7 | 100% |
|
|
|
-| 性能与兼容性 | 0 | +8(TC-15) | 8 | 100% |
|
|
|
-| **合计** | **105** | **+92** | **197** | **100%** |
|
|
|
-
|
|
|
-## 严重等级定义
|
|
|
-
|
|
|
-| 等级 | 定义 | 响应时间 |
|
|
|
-|------|------|---------|
|
|
|
-| S0-Critical | 核心链路阻塞(无法生成命盘/支付/解读) | 立即修复 |
|
|
|
-| S1-Major | 功能严重异常(计算错误/状态错乱/数据丢失) | 24h内 |
|
|
|
-| S2-Minor | 功能可用但体验缺陷(UI错位/文案错误) | 下一迭代 |
|
|
|
-| S3-Trivial | 视觉/文案微调建议 | 积攒修复 |
|
|
|
+| 后端服务 | Java Spring Boot, 端口 8186 |
|
|
|
+| 数据库 | 独立的 test 数据库(非生产) |
|
|
|
+| Dify | test 环境 Dify Chatflow API |
|
|
|
+| 测试账号 | 账号A(普通用户)、账号B(付费VIP)、账号C(带下级) |
|
|
|
+| 支付测试 | 微信沙箱环境 / Mock 模式 |
|
|
|
+
|
|
|
+### 1.4 后端架构速览
|
|
|
+
|
|
|
+| 层 | 说明 |
|
|
|
+|----|------|
|
|
|
+| Controller 9 个 | 35+ 端点,全部 POST JSON |
|
|
|
+| Entity 9 个 | User, Order, Commission, Withdraw, ChartRecord, ChatMessage, RatingAnnotation, Tag, SystemConfig |
|
|
|
+| Service 12 个 | 含 DifyService 调用外部 AI, CalculatorService 双端计算 |
|
|
|
+| 认证 | JWT token(Header `Authorization: Bearer`) |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、EPIC 1:命盘生成与展示(P0)
|
|
|
+
|
|
|
+### TC-101 生日输入与命盘生成(US-1.1)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 101.1 | 合法输入生成(客户端计算) | 无 | 输入姓名"张三"、出生日期 1990-01-01 → 点击"生成命盘" | 即时显示三角形命盘页(纯前端计算,无需网络) | S0 |
|
|
|
+| 101.2 | 年月日 picker 选择 | 无 | 分别下拉选择年/月/日 | 年份范围1900~当前年、月份1-12、日期随月份联动 | S1 |
|
|
|
+| 101.3 | 年份边界-1900 | 无 | 选择1900年 | 可选中,正常生成命盘 | S2 |
|
|
|
+| 101.4 | 年份边界-今年 | 无 | 选择当前年份 | 可选中,正常生成命盘 | S2 |
|
|
|
+| 101.5 | 月份13 | 无 | 选择月份=13 | picker不可选到13 | S2 |
|
|
|
+| 101.6 | 日期32 | 无 | 选择日期=32 | picker不可选到32 | S2 |
|
|
|
+| 101.7 | 闰年2/29 | 无 | 年份=2000,月份=2,日期=29 | 合法输入,正常生成 | S1 |
|
|
|
+| 101.8 | 姓名为空 | 无 | 不填姓名,直接点生成 | 可生成,命盘显示空字符串 | S2 |
|
|
|
+| 101.9 | 不填日期的生成 | 无 | 年月日全空,点生成 | 提示"请填写完整的出生日期" | S2 |
|
|
|
+| 101.10 | 未登录可生成 | 未登录 | 输入日期→生成命盘 | 正常生成(纯前端计算),显示结果页 | S0 |
|
|
|
+| 101.11 | 保存命盘需登录 | 未登录生成后 | 尝试保存到记录 | 弹出微信登录引导 | S0 |
|
|
|
+| 101.12 | 非VIP超配额后保存失败 | VIP非活跃+已生成3次 | 第4次点保存 | API返回1008错误:"今日命盘生成次数已达上限" | S0 |
|
|
|
+| 101.13 | VIP用户无限保存 | VIP有效 | 连续保存5次 | 每次均可正常保存(无配额限制) | S0 |
|
|
|
+| 101.14 | 跨午夜重置配额 | 非VIP 23:59 消耗3次 | 等到 00:01 后再保存 | 可正常保存(配额重置,`lastQuotaDate` 更新) | S1 |
|
|
|
+| 101.15 | 服务端同步计算 | 调用 `POST /api/chart/create` | 传入 birthday, 不传 chartData | 服务端自动通过 CalculatorService 计算 chartData | S1 |
|
|
|
+| 101.16 | 客户端/服务端计算结果一致 | 同生日 | 分别客户端 calc 和服务端 calc 对比 | 15个位置 A-O 完全一致 | S1 |
|
|
|
+| 101.17 | 弱网下客户端可看结果 | 模拟离线 | 填写后点击生成 | 前端计算正常,显示图表,保存时提示网络错误 | S1 |
|
|
|
+| 101.18 | 月份/日期个位数补零 | 月份=1,日期=1 | 生成后检查 | D=1, E=1(正确归约) | S1 |
|
|
|
+
|
|
|
+### TC-102 三角形命盘可视化(US-1.2)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 102.1 | 五层十五格完整绘制 | 生成命盘→chart页 | 5层(A-E, F-I, J-L, M-N, O) 15个位置完整显示 | S0 |
|
|
|
+| 102.2 | 布局正确性 | 检查 TriangleChart 组件渲染 | O在顶,M/N在中,F/G/H/I在底,外圈J/L/A/B/D/E | S1 |
|
|
|
+| 102.3 | 数字卡片样式 | 检查渲染 | 每个数字用独立卡片展示 | S2 |
|
|
|
+| 102.4 | 主性格 O 高亮 | O=主性格数字 | O 位置特殊样式(大号/高亮) | S1 |
|
|
|
+| 102.5 | 卓越数高亮 | 构造主性格=11/22/33 | 金底+星标+特殊样式 | S1 |
|
|
|
+| 102.6 | 姓名+生日显示 | 命盘上方 | 正确显示"张三 1990-01-01" | S2 |
|
|
|
+| 102.7 | 底部日期显示 | 命盘下方 | 显示出生日期的单独数字方框 | S2 |
|
|
|
+| 102.8 | 320px屏幕适配 | iPhone SE | 不溢出,数字不重叠 | S1 |
|
|
|
+| 102.9 | 414px屏幕适配 | iPhone Plus | 布局自适应 | S2 |
|
|
|
+| 102.10 | Android大屏适配 | 1440px宽 | 比例适配,卡片不拉伸变形 | S2 |
|
|
|
+
|
|
|
+### TC-103 数字点击查看含义(US-1.3)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 103.1 | 点击数字弹出含义 | 点击O(主性格) | 弹出面板:位置名称"主性格"、数字、性格特质 | S1 |
|
|
|
+| 103.2 | 点击不同区域数字 | 依次点击F/J/A等 | 显示对应的位置名称和描述(从 CalculatorService.getNumberMeaning/PositionName 获取) | S1 |
|
|
|
+| 103.3 | 点击空白关闭面板 | 面板打开后点空白区 | 面板关闭 | S2 |
|
|
|
+| 103.4 | 卓越数特殊含义 | 点击主性格=22数字 | 面板显示22的特殊含义("建造大师") | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、EPIC 2:分享与导出(P0)
|
|
|
+
|
|
|
+> 当前实现:分享功能仅限**推广码复制**,无图片分享/PDF导出。另见 EPIC 6 分销推广。
|
|
|
+
|
|
|
+### TC-201 推广码分享
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 201.1 | 推广码显示 | 已登录用户 | 个人中心→查看"推广码"区域 | 显示用户的 referralCode | S0 |
|
|
|
+| 201.2 | 推广码一键复制 | 点击复制按钮 | 系统提示"复制成功" | S2 |
|
|
|
+| 201.3 | 分享含 ref 参数 | 能量师分享小程序 | 分享路径应包含 `?ref=推广码` | 待实现:当前仅复制文本 | P2 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、EPIC 3:AI 解读(P0)
|
|
|
+
|
|
|
+> 架构:Dify Chatflow 对话式 AI。非静态5区解读页面。用户输入问题→AI回复。6轮对话记忆。
|
|
|
+
|
|
|
+### TC-301 AI 对话(US-3.1)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 301.1 | AI 对话入口 | 进入 chart 页 | 底部显示对话输入框 + 快捷问题(职业发展/财运分析/感情运势/健康建议) | S0 |
|
|
|
+| 301.2 | 首次进入自动问候 | 生成命盘后进入 chart 页 | AI 发送首条消息,提及主性格数字 | S0 |
|
|
|
+| 301.3 | 快捷问题发送 | 点击"职业发展" | 用户消息以快捷问题发送,AI 回复≤5秒 | S0 |
|
|
|
+| 301.4 | 自定义输入 | 输入框输入文字→发送 | 正确发送至 Dify, AI 回复正常 | S0 |
|
|
|
+| 301.5 | 空输入检查 | 输入框为空点发送 | 不发送,提示"请输入问题" | S2 |
|
|
|
+| 301.6 | 加载状态 | 等待 AI 回复 | 显示打字中/loading 动画 | S1 |
|
|
|
+| 301.7 | 对话历史持久化 | 发送3轮对话后刷新页面 | 历史消息正确恢复(ChatMessage 表查询) | S0 |
|
|
|
+| 301.8 | 对话渲染 | 长文本回复 | 自动换行,可滚动查看 | S1 |
|
|
|
+| 301.9 | 6轮记忆验证 | 连续对话6轮 | 第6轮回复能引用第1轮的上下文(Dify 对话记忆) | S1 |
|
|
|
+| 301.10 | 滚动到底部 | 新消息到达 | scroll-view 自动滚动到底部 | S2 |
|
|
|
+| 301.11 | Dify 不可用时降级 | Dify 服务宕机 | 显示"解读服务暂时不可用,请稍后再试" | S0 |
|
|
|
+| 301.12 | 用户消息保存 | 查看 ChatMessage 表 | role='user', content=用户原文, chartRecordId 正确 | S1 |
|
|
|
+| 301.13 | AI 回复保存 | 查看 ChatMessage 表 | role='ai', content=AI原文, chartRecordId 正确 | S1 |
|
|
|
+| 301.14 | 免责声明 | 对话区域底部 | 显示"本解读由AI生成,仅供参考" | S1 |
|
|
|
+
|
|
|
+### TC-302 AI 对话配额控制(US-3.2)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 302.1 | 非VIP每日1次对话限额 | 非VIP已发送1条 | 发送第2条 | 后端返回 1008:"今日AI解读次数已达上限" | S0 |
|
|
|
+| 302.2 | VIP 无限对话 | VIP 有效 | 连续发送10条 | 均可正常回复 | S0 |
|
|
|
+| 302.3 | 非VIP对话次数重置 | 非VIP 23:59 用完 | 00:01 后发送 | 可以发送(quota 跨日重置) | S1 |
|
|
|
+| 302.4 | 订阅引导卡片 | 非VIP chart 页 | 底部显示"开通VIP"引导卡片 | S1 |
|
|
|
+| 302.5 | VIP 无引导卡片 | VIP 有效 | chart 页底部 | 不显示订阅引导 | S1 |
|
|
|
+| 302.6 | 对话请求记录 | 每次对话 | ChatMessage 表 | 每次对话记录一条 user 消息 + 一条 ai 消息 | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、EPIC 4:付费与订阅(P0)
|
|
|
+
|
|
|
+> 定价:C端 ¥131/年(13100分);B端 种子价 ¥1,314(131400分)/ 标准价 ¥1,986(198600分),后台可配。
|
|
|
+
|
|
|
+### TC-401 VIP 付费开通(US-4.1)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 401.1 | 付费入口-首页引导 | 非VIP用户首页 | 显示开通引导 | S1 |
|
|
|
+| 401.2 | 付费入口-个人中心 | 非VIP个人中心 | 显示"开通VIP"按钮 | S0 |
|
|
|
+| 401.3 | 付费入口-配额用完 | 非VIP配额耗尽 | 显示引导到支付页 | S0 |
|
|
|
+| 401.4 | 付费页显示价格 | C端显示"¥131/年",B端能量师显示"¥1,314/年" | S0 |
|
|
|
+| 401.5 | "立即支付"按钮 | 支付页 | 按钮可点击,调用 `POST /api/pay/create` | S0 |
|
|
|
+| 401.6 | C端创建订单参数 | 点击支付(C端) | `totalFee=13100`(¥131),`payType='wxpay'` | S0 |
|
|
|
+| 401.7 | B端创建订单参数 | 点击支付(B端) | `totalFee=131400`(种子价¥1,314)或 `totalFee=198600`(标准价¥1,986) | S0 |
|
|
|
+| 401.8 | Mock 支付成功 | 开发模式返回 mock=true | 显示"支付成功",自动返回 | S0 |
|
|
|
+| 401.9 | 真实微信支付唤起 | prepayId 返回 | `uni.requestPayment()` 被调用 | S0 |
|
|
|
+| 401.10 | 支付成功 → VIP 升级 | 支付回调 | 调用 `userService.upgradeVip(userId, 365)`,`vipEndTime` 延后365天 | S0 |
|
|
|
+| 401.11 | 支付成功 → 订单状态 | 回调处理 | `order.status='paid'`, `order.paidAt` 设置 | S0 |
|
|
|
+| 401.12 | 续费延长 | VIP 剩余100天时续费 | `vipEndTime` 在原到期日 +365天(非覆盖) | S0 |
|
|
|
+| 401.13 | 支付失败提示 | 模拟支付取消/失败 | 显示友好提示,不丢失已填信息 | S1 |
|
|
|
+| 401.14 | 支付 loading 防重入 | 点击支付 | 按钮 loading+disabled,阻止重复点击 | S1 |
|
|
|
+| 401.15 | 超时未支付 | 创建订单后30分钟 | 订单保持 pending 状态,不自动取消 | S2 |
|
|
|
+
|
|
|
+### TC-402 订阅状态与续费(US-4.3)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 402.1 | 个人中心显示VIP状态 | VIP 有效 | 查看个人中心 | 显示"VIP" + 到期日 `vipEndTime` | S0 |
|
|
|
+| 402.2 | VIP 已过期显示 | VIP 过期后 | 查看个人中心 | 不显示 VIP 标识,`isVip()` 返回 false | S1 |
|
|
|
+| 402.3 | 到期后自动降级 | 到期日次日 | 尝试保存命盘/AI对话 | 触发配额限制(chart≤3, chat≤1) | S0 |
|
|
|
+| 402.4 | 续费按原价 | VIP 续费 | 操作续费 | C端 ¥131/年,B端 ¥1,314/年(种子价用户续费是否保留种子价需确认) | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、EPIC 5:用户与历史(P1)
|
|
|
+
|
|
|
+### TC-501 微信一键登录(US-5.1)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 501.1 | 首次使用弹授权 | 未登录用户点"保存命盘" | 弹出微信授权 | S0 |
|
|
|
+| 501.2 | 授权后自动注册+登录 | 同意授权 | 自动注册(user表创建),返回 JWT token | S0 |
|
|
|
+| 501.3 | 注册时生成推广码 | 新用户注册 | `referralCode` 字段生成8位大写字母数字串 | S1 |
|
|
|
+| 501.4 | 注册时带有效推广码 | 传入 `referralCode=ABCD1234` | `invitedBy` = 上级用户ID | S0 |
|
|
|
+| 501.5 | 注册时带无效推广码 | 传入不存在的 referralCode | 报错 1002 "Invalid referral code" | S0 |
|
|
|
+| 501.6 | 已存在用户不重复注册 | 同一 openid 再次登录 | 返回已有 token,不创建新用户 | S0 |
|
|
|
+| 501.7 | openid 来自 code | 前端传 code | 后端 `WeChatService.codeToOpenid(code)` 换取 openid | S0 |
|
|
|
+| 501.8 | 后续自动登录 | token 有效时重开小程序 | 自动登录,不弹授权 | S0 |
|
|
|
+| 501.9 | token 过期 | 2天后打开 | JWT 过期 → API 返回 1001 → 清除 token → 重新登录 | S1 |
|
|
|
+| 501.10 | 拒绝授权 | 点击"拒绝" | 可继续浏览,但不记录数据(不强制登录) | S1 |
|
|
|
+
|
|
|
+### TC-502 历史命盘记录(US-5.2)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 502.1 | "分析记录"入口 | Tab 栏 | 底部 Tab"记录" 存在 | S1 |
|
|
|
+| 502.2 | 列表倒序排列 | 保存3个命盘 | 查看记录列表 | 最新生成的在最上面 | S1 |
|
|
|
+| 502.3 | 记录显示内容 | 有历史数据 | 查看 | 姓名+生日+生成时间 + 是否已解读 | S2 |
|
|
|
+| 502.4 | 已解读标记 | 有 difyResponse 的记录 | 显示"已解读"标签 | S2 |
|
|
|
+| 502.5 | 点击记录跳转 | 点击任一条 | 跳转到 chart 页,正确加载 chartData+对话历史 | S1 |
|
|
|
+| 502.6 | 记录删除 | 长按/左滑记录 | 确认删除→调用 `POST /api/chart/delete`→从列表移除 | S1 |
|
|
|
+| 502.7 | 删除权限验证 | 用户A 删除用户B 的记录 | API 返回 1006 "无权删除此命盘" | S1 |
|
|
|
+| 502.8 | 空数据状态 | 无历史记录 | 显示"暂无命盘记录"引导文案 | S2 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、EPIC 6:分销推广与佣金(P0-P1)
|
|
|
+
|
|
|
+> 实际实现:推广码注册时自动生成(8位UUID);佣金分C端比例制(40%/5%)和B端固定制(¥500/¥100);Client端显示"推广功能开发中";服务端API已完整实现。
|
|
|
+
|
|
|
+### TC-601 推广码机制(US-6.1)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 601.1 | 注册时自动生成推广码 | 新用户注册 | 检查 User.referralCode | 8位大写字母+数字(UUID.substring(0,8).toUpperCase) | S0 |
|
|
|
+| 601.2 | 推广码全局唯一 | 并发注册1000用户 | 检查数据库 | 无重复 referralCode | S0 |
|
|
|
+| 601.3 | 个人中心显示推广码 | 已登录 | 查看个人中心→推广码区域 | 显示 referralCode + 复制按钮 | S0 |
|
|
|
+| 601.4 | 一键复制推广码 | 点击复制 | 系统提示"复制成功" | S2 |
|
|
|
+
|
|
|
+### TC-602 分享带参注册与上下级绑定(US-6.2)
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 602.1 | 新用户+有效推广码注册 | 注册传 referralCode="ABCD1234" | `User.invitedBy` = 上级ID | S0 |
|
|
|
+| 602.2 | 新用户+无效推广码注册 | 注册传不存在的码 | 报错 1002,不静默降级 | S0 |
|
|
|
+| 602.3 | 新用户+空推广码 | 注册不传 referralCode | `invitedBy = null` | S0 |
|
|
|
+| 602.4 | 已存在用户忽略推广码 | 老用户再次登录传推广码 | 不更新已有 `invitedBy` | S0 |
|
|
|
+| 602.5 | 关系终身锁定 | 绑定后 referrer 不变 | 即使再传新码也不改变 | S0 |
|
|
|
+| 602.6 | 自邀请检测 | 自己的 referralCode 绑定自己 | 代码逻辑:传入的是别人 ID,自邀请需主动检测(目前无此逻辑) | P2 |
|
|
|
+
|
|
|
+### TC-603 佣金结算(US-6.3/6.4)
|
|
|
+
|
|
|
+> 佣金规则分两套:**C端(客户)** 按比例 40%(L1)/5%(L2),定价 ¥131/年;**B端(能量师)** 固定金额 ¥500(L1)/¥100(L2),定价种子价 ¥1,314/标准价 ¥1,986。
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 603.1 | C端:有上级→L1比例佣金 | ¥131 订单,buyer.invitedBy=A | 检查 Commission 表 | level=1, toUserId=A, amount=13100×40%=5240, status="pending" | S0 |
|
|
|
+| 603.2 | C端:有上上级→L1+L2 | A→B→C, C付¥131 | Commission表 | L1给B=5240(40%), L2给A=655(5%) | S0 |
|
|
|
+| 603.3 | B端:能量师订阅→L1固定佣金 | ¥1,314 订单,buyer.invitedBy=A | 检查 Commission 表 | level=1, toUserId=A, amount=50000(¥500固定) | S0 |
|
|
|
+| 603.4 | B端:有上上级→L1+L2固定 | A→B→C, C付¥1,314 | Commission表 | L1给B=50000(¥500), L2给A=10000(¥100) | S0 |
|
|
|
+| 603.5 | 无上级不创建佣金 | buyer.invitedBy=null | 支付成功 | 不创建任何佣金记录 | S0 |
|
|
|
+| 603.6 | 有上级但上上级不存在 | parent.invitedBy=null | 创建 L1,跳过 L2 | S1 |
|
|
|
+| 603.7 | C端二级比例 5% 计算精度 | ¥131 订单,两级佣金 | L1=5240, L2=655(均为整数) | S0 |
|
|
|
+| 603.8 | B端固定金额不随价格变动 | 种子价¥1,314 vs 标准价¥1,986 | 两种价格的 L1 均为 ¥500(50000分) | S0 |
|
|
|
+| 603.9 | 重复回调幂等 | 同 outTradeNo 两次回调 | `paySuccess()` 第二次应幂等(目前无幂等检查,需注意) | S0 |
|
|
|
+| 603.10 | 佣金状态初始值 | 创建时 | status="pending" | S1 |
|
|
|
+| 603.11 | 获佣金列表 API | `POST /api/commission/list` | 返回该用户收到的佣金列表,倒序 | S1 |
|
|
|
+| 603.12 | 获佣金总额 API | `POST /api/commission/total` | 返回 status="settled" 的佣金总和 | S1 |
|
|
|
+| 603.13 | 可提现余额 API | `POST /api/withdraw/balance` | 返回 status="available" 的佣金总和 | S1 |
|
|
|
+| 603.14 | 外部能量师(非站内):无佣金 | buyer 经外部能量师推荐(非站内 user),支付 ¥131 | 检查 Commission 表 | 不创建任何佣金记录(外部能量师无站内 user id) | S1 |
|
|
|
+
|
|
|
+### TC-604 分销面板(US-6.5)
|
|
|
+
|
|
|
+> 当前 client 端仅显示"推广功能开发中"。服务端 API 已实现。
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 604.1 | 个人中心"我的推广"入口 | 任何已登录用户 | 查看个人中心 | 菜单项存在(所有用户可见,因推广码注册即有) | S1 |
|
|
|
+| 604.2 | 推广码卡片展示 | 个人中心 | 显示 referralCode+"复制" | S0 |
|
|
|
+| 604.3 | 复制推广码 | 点击复制 | 粘贴板内容 = referralCode | S2 |
|
|
|
+| 604.4 | 佣金面板 API 返回 | `POST /api/profile/commission-summary` | 返回 totalEarnings + availableBalance | S1 |
|
|
|
+| 604.5 | 佣金明细 API | `POST /api/commission/list` | 返回 Commission 列表(fromUserId/level/amount/status/createdAt) | S1 |
|
|
|
+
|
|
|
+### TC-605 提现管理(US-6.6)
|
|
|
+
|
|
|
+> 已完整实现,非"即将开放"。
|
|
|
+
|
|
|
+| # | 用例 | 前置 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|------|---------|------|
|
|
|
+| 605.1 | 提现申请-最低金额 | `POST /api/withdraw/apply` amount=9999 | 报错 1006 "Minimum withdraw is ¥100" | S0 |
|
|
|
+| 605.2 | 提现申请-合法金额 | amount=10000(¥100) | 创建 Withdraw 记录,status="pending" | S0 |
|
|
|
+| 605.3 | 提现申请-余额不足 | amount > 可用余额 | 报错 1007 "Insufficient balance" | S0 |
|
|
|
+| 605.4 | 提现列表 | `POST /api/withdraw/list` | 返回该用户所有提现记录 | S1 |
|
|
|
+| 605.5 | 可用余额查询 | `POST /api/withdraw/balance` | 返回 status="available" 的佣金总和 | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、EPIC 7:批注与客户管理(P2)
|
|
|
+
|
|
|
+### TC-701 命盘批注(US-7.1)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 701.1 | 添加批注 | `POST /api/annotation/add` | 成功创建 RatingAnnotation,status=200 | S2 |
|
|
|
+| 701.2 | 批注列表 | `POST /api/annotation/list` recordId | 返回该命盘所有批注 | S2 |
|
|
|
+| 701.3 | 删除批注 | `POST /api/annotation/delete` id | 批注删除,后续列表不再返回 | S2 |
|
|
|
+| 701.4 | 批注内容持久化 | 添加→离开→重新进入 | 批注内容正确恢复 | S2 |
|
|
|
+
|
|
|
+### TC-702 客户标签分组(US-7.2)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 702.1 | 添加标签 | `POST /api/annotation/tag/add` | 成功创建 Tag | S2 |
|
|
|
+| 702.2 | 标签列表 | `POST /api/annotation/tag/list` recordId | 返回该命盘所有标签 | S2 |
|
|
|
+| 702.3 | 删除标签 | `POST /api/annotation/tag/delete` id | 标签删除 | S2 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 九、EPIC 8:管理后台(P0-P1)
|
|
|
+
|
|
|
+### TC-801 系统配置管理(US-8.1)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 801.1 | system_config 表预置数据 | 检查 DB | 初始配置存在(chart_quota=3, chat_quota=1, share_quota=1 等) | S0 |
|
|
|
+| 801.2 | 读取配置 | `POST /api/admin/config` | 返回全部配置 key→value HashMap | S0 |
|
|
|
+| 801.3 | 更新配置 | `POST /api/admin/config/update` key+value | 写入 DB,下次读取返回新值 | S0 |
|
|
|
+| 801.4 | 动态生效 | 更新 chart_quota=5→验证生效 | 新值立即用于配额检查 | S0 |
|
|
|
+| 801.5 | 获取默认值 | 配置 key 不存在 | `getValue(key, default)` 返回默认值,不抛异常 | S1 |
|
|
|
+| 801.6 | 配置值为整数 | `getInt(key, default)` | 正确解析整数,异常时返回默认值 | S1 |
|
|
|
+
|
|
|
+### TC-802 后台用户管理(US-8.2)
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 802.1 | 管理员登录 | `POST /api/admin/login` username+password | 返回 admin JWT token | S0 |
|
|
|
+| 802.2 | 登录凭证错误 | 错误密码 | 返回 1001 "Invalid admin credentials" | S0 |
|
|
|
+| 802.3 | 用户列表 | `POST /api/admin/users` | 返回全部 User 列表 | S1 |
|
|
|
+| 802.4 | 升级 VIP | `POST /api/admin/user/upgrade` userId | user.vipEndTime = now+1年 | S0 |
|
|
|
+| 802.5 | 降级 VIP | `POST /api/admin/user/downgrade` userId | user.vipEndTime = null | S0 |
|
|
|
+| 802.6 | 设置管理员 | `POST /api/admin/user/set-admin` userId+isAdmin | user.isAdmin 更新 | S1 |
|
|
|
+| 802.7 | 不存在的用户升级 | 传入 userId=-1 | 返回 1002 "User not found" | S1 |
|
|
|
+
|
|
|
+### TC-803 后台订单管理
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 803.1 | 订单列表 | `POST /api/admin/orders` | 返回全部 Order 列表(id/userId/outTradeNo/totalFee/status/payType/paidAt) | S1 |
|
|
|
+| 803.2 | 订单金额单位为分 | 检查 totalFee | 整型,单位分(C端¥131=13100,B端种子价¥1,314=131400) | S2 |
|
|
|
+
|
|
|
+### TC-804 后台佣金管理
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 804.1 | 佣金列表 | `POST /api/admin/commissions` | 返回全部 Commission 列表(含 level/amount/status) | S1 |
|
|
|
+| 804.2 | 所有命盘列表 | `POST /api/admin/charts` | 返回全部 ChartRecord 列表 | S1 |
|
|
|
+
|
|
|
+### TC-805 后台提现管理
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 805.1 | 待审核提现列表 | `POST /api/admin/withdraws` | 返回 status="pending" 的 Withdraw 列表 | S1 |
|
|
|
+| 805.2 | 审核通过 | `POST /api/admin/withdraw/approve` id | withdraw.status="approved" | S0 |
|
|
|
+| 805.3 | 审核拒绝 | `POST /api/admin/withdraw/reject` id | withdraw.status="rejected" | S0 |
|
|
|
+
|
|
|
+### TC-806 后台统计看板
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| 806.1 | 统计看板 | `POST /api/admin/stats` | 返回 totalUsers/vipUsers/totalOrders/totalCharts/totalCommissions/totalRevenue/recentOrders | S0 |
|
|
|
+| 806.2 | totalRevenue 计算 | 有 paid 订单 | 仅统计 status="paid" 的订单 totalFee 之和 | S0 |
|
|
|
+| 806.3 | vipUsers 统计 | 有未过期 VIP | `countByVipEndTimeAfterAndVipEndTimeIsNotNull(now)` | S0 |
|
|
|
+| 806.4 | recentOrders 最多10条 | 订单>10 | 仅返回最近10条,按 id desc | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十、计算引擎专项测试
|
|
|
+
|
|
|
+### TC-CALC 核心算法(双端一致性)
|
|
|
+
|
|
|
+| # | 用例 | 输入 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| CALC.1 | reduceToDigit 个位数 | 5 | 5 | S0 |
|
|
|
+| CALC.2 | reduceToDigit 两位数归约 | 10 | 1 | S0 |
|
|
|
+| CALC.3 | reduceToDigit 多位数归约 | 99 | 9 | S0 |
|
|
|
+| CALC.4 | reduceToDigit 多级归约 | 999 → 27 → 9 | 9 | S0 |
|
|
|
+| CALC.5 | reduceToDigit 卓越数11 | 11 | 11 | S0 |
|
|
|
+| CALC.6 | reduceToDigit 卓越数22 | 22 | 22 | S0 |
|
|
|
+| CALC.7 | reduceToDigit 卓越数33 | 33 | 33 | S0 |
|
|
|
+| CALC.8 | 完整命盘-标准日期 | 1990-01-01 | A=1,B=9,C=9,D=1,E=1,F=1,G=9,H=1,I=2,J=1,K=1,L=3,M=2,N=4,O=6 | S0 |
|
|
|
+| CALC.9 | 月份两位数 | 1985-12-25 | D=1+2=3, E=2+5=7 | S0 |
|
|
|
+| CALC.10 | 年份特殊 | 2001-03-08 | A=2, B=0, C=0+1=1 | S0 |
|
|
|
+| CALC.11 | 主性格卓越数 | 构造使 O=11/22/33 | 归约在卓越数停止,不继续归约 | S0 |
|
|
|
+| CALC.12 | 全部相同数字 | 1111-11-11 | 计算正确,不失精度 | S1 |
|
|
|
+| CALC.13 | 全部9 | 9999-09-09 | 计算正确 | S1 |
|
|
|
+| CALC.14 | 客户端/服务端计算结果完全一致 | 1995-07-15 | 客户端 calculator.js 结果 = 服务端 CalculatorService 结果 | S0 |
|
|
|
+| CALC.15 | getNumberMeaning 1-9 + 11/22/33 | 每个数字 | 返回正确的 title/trait/color | S1 |
|
|
|
+| CALC.16 | getPositionName 15个位置 | A-O 每个 | 返回正确中文名称(A=年位一 ... O=主性格) | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十一、服务端 API 集成测试
|
|
|
+
|
|
|
+### TC-API 认证
|
|
|
+
|
|
|
+| # | 用例 | 请求 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| API.1 | 微信登录 | `POST /api/auth/login` {openid, nickname, avatarUrl} | 返回 JWT token,新用户自动注册 | S0 |
|
|
|
+| API.2 | 微信登录+推广码 | `POST /api/auth/login` {openid, referralCode} | 新用户 invitedBy=上级ID | S0 |
|
|
|
+| API.3 | 重复登录 | 同一 openid 两次登录 | 返回已有 token,不创建新用户 | S0 |
|
|
|
+| API.4 | 无 token 调用需鉴权 API | `POST /api/chart/list` 无 Authorization | 返回 401 或错误 | S0 |
|
|
|
+| API.5 | 无效 token | Authorization: Bearer invalid | 返回 1001 未授权 | S0 |
|
|
|
+
|
|
|
+### TC-API 命盘
|
|
|
+
|
|
|
+| # | 用例 | 请求 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| API.6 | 创建命盘(服务端计算) | `POST /api/chart/create` {birthday, name} | 返回 ChartRecord,chartData 由服务端计算 | S0 |
|
|
|
+| API.7 | 创建命盘(客户端传入) | `POST /api/chart/create` {birthday, name, chartData} | 返回 ChartRecord,chartData 使用客户端的 | S1 |
|
|
|
+| API.8 | 创建命盘超过配额 | 非VIP第4次创建 | 报错 1008 配额超限 | S0 |
|
|
|
+| API.9 | 命盘列表 | `POST /api/chart/list` | 返回该用户所有命盘(userId 从 token 获取) | S1 |
|
|
|
+| API.10 | 命盘详情 | `POST /api/chart/detail` {id} | 返回 ChartRecord 含 chartData, difyResponse | S1 |
|
|
|
+| API.11 | 删除自己的命盘 | `POST /api/chart/delete` {id} | 删除成功 | S1 |
|
|
|
+| API.12 | 删除他人的命盘 | 用户A 删 用户B 的命盘 | 报错 1006 "无权删除此命盘" | S1 |
|
|
|
+
|
|
|
+### TC-API AI对话
|
|
|
+
|
|
|
+| # | 用例 | 请求 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| API.13 | 发送消息 | `POST /api/chat/send` {chartRecordId, query} | 返回 AI 回复内容 | S0 |
|
|
|
+| API.14 | 访问他人命盘 | 用户A 查看 用户B 的 chartRecordId | 报错 1006 "无权访问此命盘" | S0 |
|
|
|
+| API.15 | 对话历史 | `POST /api/chat/history` {chartRecordId} | 返回 ChatMessage[],按 createdAt 升序 | S1 |
|
|
|
+| API.16 | 空历史 | 从未对话的命盘 | 返回空数组 [] | S1 |
|
|
|
+| API.17 | 对话超配额 | 非VIP超过1条 | 报错 1008 | S0 |
|
|
|
+
|
|
|
+### TC-API 支付
|
|
|
+
|
|
|
+| # | 用例 | 请求 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| API.18 | 创建订单 | `POST /api/pay/create` {totalFee:39800, payType:'wxpay'} | 返回 Order,status='pending' | S0 |
|
|
|
+| API.19 | 支付回调 | `POST /api/pay/notify` {outTradeNo} | order.status='paid',VIP 升级,佣金创建 | S0 |
|
|
|
+| API.20 | 重复回调 | 同 outTradeNo 两次 | 第二次 VIP 不重复加天数,佣金不重复创建(当前无幂等,需验证) | S1 |
|
|
|
+| API.21 | 不存在的订单回调 | outTradeNo 随机 | 报错 1005 "Order not found" | S1 |
|
|
|
+
|
|
|
+### TC-API 提现
|
|
|
+
|
|
|
+| # | 用例 | 请求 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| API.22 | 提现申请-低于最低 | `POST /api/withdraw/apply` {amount:9999} | 报错 1006 | S0 |
|
|
|
+| API.23 | 提现申请-合法 | amount:10000 | 返回 Withdraw,status='pending' | S0 |
|
|
|
+| API.24 | 余额不足 | amount > availableBalance | 报错 1007 | S0 |
|
|
|
+| API.25 | 提现列表 | `POST /api/withdraw/list` | 返回该用户所有提现记录 | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十二、边界与异常测试
|
|
|
+
|
|
|
+### TC-ERR 输入边界
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| ERR.1 | 年月日全部为空 | 点生成 | 提示"请填写完整的出生日期" | S2 |
|
|
|
+| ERR.2 | 月份=0 | 输入 | 提示"请输入正确的月份(1-12)" | S2 |
|
|
|
+| ERR.3 | 月份=13 | 输入 | 提示同上 | S2 |
|
|
|
+| ERR.4 | 日期=0 | 输入 | 提示"请输入正确的日期" | S2 |
|
|
|
+| ERR.5 | 日期=32 | 输入 | 提示同上 | S2 |
|
|
|
+| ERR.6 | 姓名为空 | 生成命盘 | 显示空字符串 | S2 |
|
|
|
+| ERR.7 | 姓名超长 | 输入51字符 | 数据库 varchar(50) 截断风险(需前段限制) | S2 |
|
|
|
+| ERR.8 | API 传不存在的 referralCode | POST /api/auth/login | 报错 1002 | S1 |
|
|
|
+| ERR.9 | 超长 outTradeNo | 数据库 varchar(64) | 不溢出,正常写入 | S1 |
|
|
|
+
|
|
|
+### TC-ERR 服务端异常
|
|
|
+
|
|
|
+| # | 用例 | 步骤 | 预期结果 | 等级 |
|
|
|
+|---|------|------|---------|------|
|
|
|
+| ERR.10 | Dify API 超时 | Dify 服务不可用 | `DifyService.invokeChatflow` 抛异常 → `ChatService` 捕获返回"解读服务暂时不可用" | S1 |
|
|
|
+| ERR.11 | 数据库连接失败 | DB 宕机 | API 返回 500,不暴露堆栈 | S1 |
|
|
|
+| ERR.12 | 订单创建后未支付 | pending 订单一直存在 | 不影响配额,不自动取消 | S2 |
|
|
|
+| ERR.13 | 并发创建相同 outTradeNo | 极高并发 | outTradeNo 含毫秒时间戳+UUID6位,冲突概率极低 | S1 |
|
|
|
+| ERR.14 | 命盘ID不存在 | detail/delete 传 id=-1 | 报错 1004 "Chart record not found" | S1 |
|
|
|
+| ERR.15 | delete 自己不存在的记录 | 无权限 delete | 报错 1006 | S1 |
|
|
|
+
|
|
|
+### TC-ERR 应用级异常
|
|
|
+
|
|
|
+| # | 用例 | 验证点 | 预期结果 | 等级 |
|
|
|
+|---|------|--------|---------|------|
|
|
|
+| ERR.16 | token 过期 | API 返回 1001 | 清除本地 token,回到登录状态 | S1 |
|
|
|
+| ERR.17 | VIP 过期自动降级 | vipEndTime < now | isVip()=false,配额限制恢复 | S0 |
|
|
|
+| ERR.18 | 支付重入 | 快速连点支付按钮 | payLoading=true 阻止第二次 | S1 |
|
|
|
+| ERR.19 | 退出登录状态 | 退出→重进个人中心 | 显示未登录状态,无用户信息 | S1 |
|
|
|
+| ERR.20 | 页面卸载未释放 | setInterval | 页面 onUnload 时 clearInterval | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十三、合规与安全测试
|
|
|
+
|
|
|
+### TC-COMP 合规检查
|
|
|
+
|
|
|
+| # | 检查项 | 通过标准 | 等级 |
|
|
|
+|---|--------|---------|------|
|
|
|
+| COMP.1 | 首页/解读文案 | 不含"算命、占卜、预测、占星" | S0 |
|
|
|
+| COMP.2 | AI 解读免责声明 | 页末含"本解读由AI生成,仅供参考" | S0 |
|
|
|
+| COMP.3 | 用户协议链接 | 可点击,打开有效页面 | S0 |
|
|
|
+| COMP.4 | 隐私政策链接 | 可点击,打开有效页面 | S0 |
|
|
|
+| COMP.5 | 不收集敏感信息 | 无身份证/银行卡输入 | S0 |
|
|
|
+| COMP.6 | 支付合规 | 微信支付规范,无诱导消费/虚假倒计时 | S0 |
|
|
|
+| COMP.7 | 分销合规 | 两级分销,无团队计酬,无入门费 | S0 |
|
|
|
+| COMP.8 | 分销文案合规 | 无"拉人头、团队计酬、入门费"等涉传表述 | S0 |
|
|
|
+| COMP.9 | AppID 配置正确 | manifest.json wx5ba8038ef16fb245 | S1 |
|
|
|
+| COMP.10 | JWT Secret 不硬编码 | application.yml 配置 | S0 |
|
|
|
+| COMP.11 | Dify API Key 不暴露前端 | 仅 Server DifyService 持有 | S0 |
|
|
|
+| COMP.12 | 支付商户号配置化 | 不硬编码,配置注入 | S1 |
|
|
|
+| COMP.13 | 用户数据删除 | 退出登录选项 | S2 |
|
|
|
+| COMP.14 | API鉴权 | 所有非公开接口需 JWT token | S0 |
|
|
|
+| COMP.15 | 命盘数据隔离 | 用户只能查看/删除自己的命盘 | S0 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十四、性能测试
|
|
|
+
|
|
|
+### TC-PERF 性能指标
|
|
|
+
|
|
|
+| # | 场景 | 方法 | 目标 | 等级 |
|
|
|
+|---|------|------|------|------|
|
|
|
+| PERF.1 | 命盘生成(客户端计算公式) | 前端计时 | <500ms | S0 |
|
|
|
+| PERF.2 | AI 对话回复(Dify API 调用) | 全链路计时 | <5000ms | S0 |
|
|
|
+| PERF.3 | TriangleChart 组件渲染 | 渲染计时 | <500ms | S1 |
|
|
|
+| PERF.4 | 首页首屏加载 | 小程序启动 | <2000ms | S1 |
|
|
|
+| PERF.5 | 历史列表渲染 | 100条记录 | 无白屏/卡顿 | S1 |
|
|
|
+| PERF.6 | 服务端 API 响应 | 典型请求 | <200ms(不含 Dify) | S1 |
|
|
|
+| PERF.7 | 并发用户 100 | 压测 API | 正确率 100%,P95 <500ms | S2 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十五、真机兼容性测试
|
|
|
+
|
|
|
+### TC-DEV 设备矩阵
|
|
|
+
|
|
|
+| # | 设备 | iOS/Android | 微信版本 | 重点验证 | 等级 |
|
|
|
+|---|------|-------------|---------|---------|------|
|
|
|
+| DEV.1 | iPhone SE (3rd) | iOS 16+ | 8.0+ | TriangleChart 适配、布局无溢出 | S1 |
|
|
|
+| DEV.2 | iPhone 13/14 | iOS 16+ | 8.0+ | 核心流程全链路 | S0 |
|
|
|
+| DEV.3 | iPhone 15 Pro Max | iOS 17+ | 8.0+ | 大屏适配、对话体验 | S1 |
|
|
|
+| DEV.4 | 华为Mate 60 | Android 14 | 8.0+ | 核心流程+TriangleChart | S0 |
|
|
|
+| DEV.5 | 小米14 | Android 14 | 8.0+ | 核心流程+支付 | S1 |
|
|
|
+| DEV.6 | OPPO Reno 10 | Android 13 | 8.0+ | 支付流程+分销 | S1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十六、回归测试矩阵(核心P0冒烟)
|
|
|
+
|
|
|
+上线前必须通过以下 P0 用例:
|
|
|
+
|
|
|
+| ID | 描述 |
|
|
|
+|----|------|
|
|
|
+| 101.1 | 合法输入生成命盘 |
|
|
|
+| 101.10 | 未登录可生成 |
|
|
|
+| 101.12 | 非VIP超配额限制 |
|
|
|
+| 101.13 | VIP用户无限生成 |
|
|
|
+| 102.1 | 五层十五格完整 |
|
|
|
+| 301.1 | AI对话入口存在 |
|
|
|
+| 301.2 | 首次进入自动问候 |
|
|
|
+| 301.3 | 快捷问题发送成功 |
|
|
|
+| 301.7 | 对话历史持久化 |
|
|
|
+| 301.11 | Dify不可用时降级 |
|
|
|
+| 302.1 | 非VIP每日1次限额 |
|
|
|
+| 302.2 | VIP无限对话 |
|
|
|
+| 401.4 | 付费页显示¥131/年 |
|
|
|
+| 401.6 | C端创建订单参数(13100) |
|
|
|
+| 401.7 | B端创建订单参数(131400) |
|
|
|
+| 401.9 | 支付成功→VIP升级 |
|
|
|
+| 501.1 | 首次使用弹授权 |
|
|
|
+| 501.4 | 有效推广码绑定 |
|
|
|
+| 501.6 | 已存在用户不重复注册 |
|
|
|
+| 601.1 | 注册时自动生成推广码 |
|
|
|
+| 603.1 | C端比例佣金 L1=40%(¥5240) |
|
|
|
+| 603.2 | C端比例佣金 L1+L2(40%+5%) |
|
|
|
+| 603.3 | B端固定佣金 L1=¥500 |
|
|
|
+| 603.4 | B端固定佣金 L1+L2(¥500+¥100) |
|
|
|
+| 603.5 | 无上级不创建佣金 |
|
|
|
+| 605.1 | 提现最低金额检查 |
|
|
|
+| 605.2 | 提现申请合法金额 |
|
|
|
+| 801.1 | 系统配置预置数据 |
|
|
|
+| 801.4 | 配置动态生效 |
|
|
|
+| 802.4 | 后台升级VIP |
|
|
|
+| 805.2 | 后台提现审核通过 |
|
|
|
+| 806.1 | 统计看板返回正确 |
|
|
|
+| API.1 | 微信登录返回JWT |
|
|
|
+| API.4 | 无token鉴权拒绝 |
|
|
|
+| API.13 | 发送消息成功 |
|
|
|
+| API.18 | 创建订单成功 |
|
|
|
+| API.19 | 支付回调成功 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十七、测试数据准备清单
|
|
|
+
|
|
|
+| 数据项 | 数量 | 说明 |
|
|
|
+|--------|------|------|
|
|
|
+| 测试微信账号A | 1 | 普通用户(无VIP) |
|
|
|
+| 测试微信账号B | 1 | VIP有效用户 |
|
|
|
+| 测试微信账号C | 1 | 带下级关系的用户(有佣金数据) |
|
|
|
+| Dify test环境 | 1 | test API key + base-url |
|
|
|
+| 数据库 test 实例 | 1 | 独立Mysql,非生产 |
|
|
|
+| 真机设备 | ≥2台 | iOS + Android 各覆盖 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 附录:用例覆盖度统计
|
|
|
+
|
|
|
+| EPIC | 模块 | 用例数 | P0 | P1 | P2 |
|
|
|
+|------|------|--------|----|----|-----|
|
|
|
+| EPIC 1 | 命盘生成与展示 | 33 | 12 | 16 | 5 |
|
|
|
+| EPIC 2 | 分享与导出 | 3 | 2 | 0 | 1 |
|
|
|
+| EPIC 3 | AI 解读 | 19 | 12 | 5 | 2 |
|
|
|
+| EPIC 4 | 付费与订阅 | 19 | 15 | 3 | 1 |
|
|
|
+| EPIC 5 | 用户与历史 | 18 | 8 | 9 | 1 |
|
|
|
+| EPIC 6 | 分销推广与佣金 | 29 | 18 | 9 | 2 |
|
|
|
+| EPIC 7 | 批注与客户管理 | 7 | 0 | 0 | 7 |
|
|
|
+| EPIC 8 | 管理后台 | 19 | 12 | 6 | 1 |
|
|
|
+| — | 计算引擎 | 16 | 10 | 6 | 0 |
|
|
|
+| — | 服务端API集成 | 25 | 16 | 8 | 1 |
|
|
|
+| — | 边界与异常 | 20 | 6 | 12 | 2 |
|
|
|
+| — | 合规安全 | 15 | 11 | 3 | 1 |
|
|
|
+| — | 性能 | 7 | 4 | 3 | 0 |
|
|
|
+| — | 真机兼容 | 6 | 2 | 4 | 0 |
|
|
|
+| **合计** | | **236** | **128** | **84** | **24** |
|
|
|
+
|
|
|
+> P0 用例 128 条,P1 84 条,P2 24 条,**总计 236 条测试用例**。
|
|
|
+> 冒烟测试(P0核心 34 条)通过后方可进入发布流程。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## v3.0 变更日志
|
|
|
+
|
|
|
+| 变更 | 说明 |
|
|
|
+|------|------|
|
|
|
+| 📉 价格修正 | ¥1,314/¥1,914+¥299 → ¥398统一定价,移除种子价/标准价逻辑 |
|
|
|
+| 🔄 佣金修正 | 固定金额¥500/¥100+40%/5% → 统一30%+10%百分比 |
|
|
|
+| 🔄 AI架构 | 静态5区解读 → Dify Chatflow 对话式AI,6轮记忆 |
|
|
|
+| 🔄 推广码 | 支付后生成6位码 → 注册时生成8位UUID码 |
|
|
|
+| 📉 分销面板 | 详尽6区UI → 服务端API已实现,client显示"开发中" |
|
|
|
+| ✅ 提现 | Phase1"即将开放" → 已完整实现(apply/approve/reject) |
|
|
|
+| 🔄 用户模型 | vipType+practitioner+3个统计字段 → 单一vipEndTime |
|
|
|
+| 🔄 角色系统 | 移除practitioner/annual角色,仅VIP/非VIP两级 |
|
|
|
+| 📉 分享导出 | 10+7条 → 仅保留推广码复制 |
|
|
|
+| ✅ 管理后台 | 新增:提现审核、统计看板、KV配置管理 |
|
|
|
+| ✅ Dify集成 | 新增DifyService/ChatService测试覆盖 |
|
|
|
+| 🔄 云函数测试 | 迁移为Server API集成测试(8个Controller 25+端点) |
|
|
|
+| 📉 真机兼容 | 8设备→6设备(移除iPad/折叠屏) |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## v3.1 变更日志
|
|
|
+
|
|
|
+| 变更 | 说明 |
|
|
|
+|------|------|
|
|
|
+| 🔄 价格模型 | ¥398统一定价 → 分C端¥131/年 + B端种子价¥1,314/标准价¥1,986 |
|
|
|
+| 🔄 佣金规则 | 统一30%+10% → C端比例40%(L1)/5%(L2) + B端固定¥500(L1)/¥100(L2) |
|
|
|
+| 🔄 TC-603重构 | 10条旧用例→14条新用例,覆盖C端比例/B端固定/内外部推荐场景 |
|
|
|
+| 🔄 TC-401更新 | 拆分C端/B端创建订单参数,更新定价显示用例 |
|
|
|
+| ➕ 新增用例 | +5条(TC-401 1条 + TC-603 4条) |
|
|
|
+| ➕ 新增P0 | +6条(TC-401.7 + TC-603.1~603.5,603.7~603.9) |
|
|
|
+| ➕ 603.14 | 新增"外部能量师推荐(非站内user)不创建佣金"边界用例 |
|