← BACK · 返回原型集
V1.0 14 / QA TEST PLAN DUOBAO
QUALITY ASSURANCE · 测试方案

QA 测试方案 V1.0 DUOBAO TEST STRATEGY · UNIT · CONTRACT · INTEGRATION · E2E · CHAIN

这页把要测什么、怎么测、谁测、什么时候测讲清楚。 覆盖 9 个后端服务 + 一个前端 + 双链(BSC / TRON)。 v1.0 的承诺是:线上事故 = 0,资金账本 100% 自洽,签名流程零绕过。 所有具体用例数和覆盖率都跟随 sprint 在 CI 自动统计,这页给的是范围和门槛

5
Test Tiers
unit · contract · integration · e2e · manual
9
Backend Services
user / wallet / order / ticket / game / chain / sign / risk / withdraw
2
Chains
BSC + TRON,各自 testnet (BSC Testnet / Nile)
4
CI Gates
PR / merge / staging / release
SECTION 01 · STRATEGY

测试金字塔 TEST PYRAMID

用例数从下往上递减,执行成本和稳定性反向。 每一层只测本层职责,不替代下层(如:E2E 不替代 unit 检查 null)。 百分比是用例条数占比,不是覆盖率指标。

L1 · Unit
单元测试
单个类、单个方法,纯 JVM,无 DB / 无 Redis / 无网络。JUnit5 + Mockito + AssertJ。
~60%
L2 · Contract
契约测试
Feign 接口、Kafka topic schema、对外 REST API。FeignClientSurfaceTest 已锁定 11 个 client。
~12%
L3 · Integration
集成测试
单个服务起完整 Spring 上下文,接 Testcontainers 起的真 MySQL / Redis / Kafka,跨多个 component。
~18%
L4 · E2E
端到端
docker-compose 起整套后端 + 前端,跑完整业务流程(登录-下单-开奖-提现)。BSC Testnet / TRON Nile 真链。
~8%
L5 · Manual
人工探索
UI 视觉、风控规则误杀、运营后台权限边界、应急预案演练。release 前必跑。
~2%
SECTION 02 · COVERAGE MATRIX

各服务测试范围 PER-SERVICE TEST SCOPE

每个后端服务必测什么。覆盖率列是 v1.0 GA 的最低门槛(行覆盖率,Jacoco 统计,跨 src/main/java)。低于门槛的 PR 不允许 merge。

SERVICE
测试重点
UNIT
INTEG
E2E
user-service用户服务
TG OAuth 校验、JWT 签发/校验、风控字段写入。VerifyTgOAuthService 必须覆盖全部失败分支(timestamp 漂移、hash 不匹配、bot token 错配)。
≥ 80%
必须
必须
wallet-service钱包服务
余额扣减/退款幂等性、归集阈值触发、HD 派生 index 唯一性、热钱包 ↔ 冷钱包阈值告警逻辑。
≥ 85%
必须
必须
order-service下单服务
下单幂等键、库存(剩余票数)行锁、支付状态机、超时/取消、并发抢票。
≥ 80%
必须
必须
ticket-service票务服务
票号生成唯一性、活动票池容量、随机票发放、票↔订单关联完整性。
≥ 75%
必须
推荐
game-service活动/开奖
DrawEngine 三种实现(BACKEND / VRF_ONLY / FULL_CHAIN)各自的中奖号计算、回调幂等、奖金分配账本。
≥ 85%
必须
必须
chain-service链路服务
ChainAdapter (BSC / TRON) 各自的 verify-claim、扫块对账、广播失败重试、nonce 管理、gas 估算。
≥ 75%
必须
必须
sign-service签名服务
HD 派生路径正确性、签名输出确定性、KMS 调用边界、内部 RBAC、私钥不外泄断言(写一条 test 显式验证 master seed 不出现在 stack/log)。
≥ 90%
必须
推荐
risk-service风控(占位)
v1.0 placeholder。提现限额、地址黑名单、KYC 状态校验逻辑驻留 withdraw-service,但 risk-service 接口边界要有 mock 测试。
≥ 60%
推荐
N/A
withdraw-service出款服务
出款状态机 PENDING→SIGNING→BROADCASTED→CONFIRMED/FAILED 全路径、风控前置、大额二审、签名前 risk 复核、广播失败 DLQ。
≥ 85%
必须
必须
SECTION 03 · END-TO-END

关键 E2E 业务流程 CRITICAL E2E SCENARIOS

每个流程都跑happy path + 至少 1 个失败路径。 失败路径要验证账本回滚 / 余额一致 / 队列状态正确,不只是看错误码。

① TG 登录注册 TELEGRAM OAUTH LOGIN

用户首次通过 TG 进入小程序,完成登录、获取 JWT。
  • P1 · TG OAuth 回调 → user-service verifyTgOAuth → JWT 返回 → 前端存储 → 调 /api/v1/user/me 通过
  • F1 · timestamp 早于当前时间 24h → 拒签 USER_TG_AUTH_EXPIRED
  • F2 · hash 由错误 bot token 计算 → 拒签 USER_TG_AUTH_INVALID,不写库
断言:成功路径 user 表只新增 1 条,user_chain_addr 表为空(等首次充值才派生)。

② USDT 充值 + 归集 DEPOSIT + SWEEP

用户从外部钱包转 USDT 到平台派生地址,触发归集。
  • P1 · 用户提交 txHash → chain-service verify-claim → 余额到账
  • P2 · 余额超过归集阈值 → wallet-service sweep → sign-service 签名 → chain-service 广播 → 到达热钱包
  • F1 · txHash 不存在或未确认 → 不绑定,事件入异常队列
  • F2 · 归集广播失败 (RPC 超时) → 重试 3 次 → 入 DLQ → 告警
断言:链上 USDT 余额 = 派生地址 + 热钱包 + DLQ 待处理,差额为 0。

③ 购票 BUY TICKET

用户从内部余额下单买票,链下扣减、活动奖池增加。
  • P1 · 余额充足 → 下单成功 → 票号写入 ticket → 余额扣减 → 奖池累加
  • P2 · 同一幂等键重复请求 → 返回首次结果,不重复扣款
  • F1 · 余额不足 → WALLET_BALANCE_INSUFFICIENT,无任何账本变更
  • F2 · 100 并发抢最后 1 张票 → 仅 1 单成功,其余 TICKET_SOLD_OUT
断言:用户余额 + 已扣金额 = 下单前余额;售出票数 ≤ 活动总票数。

④ 开奖(VRF_ONLY) DRAW · VRF_ONLY

活动售罄或截止时间到,触发 BSC 上 Chainlink VRF 拿随机数,确定中奖票。
  • P1 · game-service trigger → chain-service requestRandomWords → BSC fulfillRandomWords 回调 → 写 vrf_request 表 → 算中奖号 → 派奖
  • P2 · TRON 活动回退 BACKEND 模式(VRF 不在 TRON),后端 commit-reveal 出号
  • F1 · VRF 回调超过 6 个区块未到 → 重发请求 + 告警
  • F2 · 同一 requestId 重复回调 → 幂等丢弃,只入账一次
断言:中奖号 = mod(vrf_random, total_tickets) + 1;奖池余额 = 中奖金额 + 平台佣金。

⑤ 提现 WITHDRAW

用户发起提现,经风控、签名、广播,USDT 从热钱包打到用户外部地址。
  • P1 · 小额 (≤ 限额) → 风控通过 → SIGNING → BROADCASTED → CONFIRMED → 余额扣减
  • P2 · 大额 (> 单笔上限) → 进入二审队列 → 运营审批 → 继续走流程
  • F1 · 提现地址在黑名单 → WITHDRAW_ADDRESS_BLOCKED,余额不动
  • F2 · 链上广播失败 → 状态退回 PENDING_RETRY → 重试 → 仍失败入 DLQ → 余额回滚
断言:CONFIRMED 状态时,链上 transfer event 与出款记录一一对应;FAILED 时余额完全回滚。

⑥ 冷热钱包再平衡 HOT-COLD REBALANCE

热钱包余额超阈值自动转冷;低于阈值告警等运营人工补回。
  • P1 · 热钱包余额 > 上限 → 自动 transfer 差额到冷钱包 → multisig 确认
  • P2 · 热钱包余额 < 下限 → Prometheus alert → 钉钉/PagerDuty 通知
  • F1 · 自动转账广播失败 → 重试 + 告警,不影响出款主路径
断言:阈值参数从 Nacos 热加载;rebalance event 全部入 audit log。
SECTION 04 · ON-CHAIN

链上专项测试 ON-CHAIN TEST PLAN

BSC + TRON 各自一套测试,用真实 testnet,不用纯 mock。原因:RPC 行为、gas 计费、event log 编码这些细节只有真链才会暴露。

BSC Testnet CHAPMAN-97

  • USDT 模拟合约:部署一份 BEP20 mock,水龙头自由 mint
  • VRF v2.5:用 BSC testnet 真 Coordinator,subscription 充测试 LINK
  • 覆盖项:verify-claim / sweep / withdraw / VRF round-trip / event log 解析
  • 性能:single-node Geth + 30 TPS 持续 10 分钟

TRON Nile SHASTA-201

  • USDT 模拟合约:TRC20 mock,Nile 水龙头领 TRX
  • VRF:TRON 链不接 Chainlink VRF,降级 BACKEND 模式
  • 覆盖项:verify-claim / sweep / withdraw / TRC20 event 解析 / TVM 计费差异
  • 性能:Nile 公共节点 + 10 TPS 持续 10 分钟

边界 + 失败 EDGE & FAILURE

  • RPC 节点切换:杀掉主节点 → 自动 failover 到备节点
  • 区块重组:回退确认深度,验证账本不重复入账
  • nonce 错乱:并发 5 笔提现,nonce 必须递增不冲突
  • gas 价格突变:gas 翻 10 倍,不触发资金被卡
SECTION 05 · SECURITY

安全测试清单 SECURITY CHECKLIST

legacy 项目踩过 fastjson RCE、predictable random、unverified JWT、git 历史泄密。 v1.0 必须每项都有 test 显式覆盖,在 CI 跑。

认证 / 授权 AUTH

  • JWT 签名验证:篡改 payload / 错误密钥 / 过期 token,必须 401
  • TG OAuth hash:用错误 bot token 计算的 hash,必须拒签
  • 水平越权:用户 A 的 token 访问用户 B 的资源,必须 403
  • 垂直越权:普通用户 token 访问 admin API,必须 403

注入 / RCE INJECTION

  • SQL 注入:Mybatis 全部走 parameter binding,扫 ${} 拼接告警
  • JSON 反序列化:禁用 fastjson,jackson 关闭 enableDefaultTyping
  • XSS:前端 markdown 渲染走 DOMPurify
  • 命令注入:任何 Runtime.exec 调用必须 review

密钥 / 私钥 SECRETS

  • git 历史扫描:CI 跑 gitleaks,任何 secret 阻断 merge
  • sign-service 隔离:断言 master seed 不出现在 log / stack trace / metric label
  • KMS 调用边界:只在 sign-service 进程内调用,gRPC 接口 mTLS 双向认证
  • 冷钱包私钥:不存在任何代码路径,multisig + 硬件签名,本测试只验证不可达

链上专项 ON-CHAIN

  • 随机数:不允许使用 block.prevrandao / block.timestamp 当随机源
  • 重放攻击:VRF 回调、verify-claim、提现广播必须幂等
  • 合约升级:v1.0 不部署可升级 proxy,所有 onchain 逻辑 immutable
  • 地址黑名单:OFAC / 自维护黑名单 + 提现地址 prefix 白名单
SECTION 06 · PERFORMANCE

性能与压测 LOAD & STRESS

v1.0 不追求海量并发。压测目标:验证开奖时段、提现高峰下系统不雪崩,链上 RPC 不被限流。

下单峰值 ORDER PEAK

  • 场景:活动倒计时 1 分钟,1000 用户抢 100 张票
  • 目标:p95 下单延迟 ≤ 800ms,无超卖
  • 工具:k6 + 预热场景
  • 失败定义:任何超卖 / 余额负数 / 队列堆积 > 5s

提现高峰 WITHDRAW PEAK

  • 场景:200 笔提现 5 分钟内提交
  • 目标:CONFIRMED 平均 ≤ 90s (BSC) / ≤ 60s (TRON)
  • 工具:k6 + 自动监听链上 receipt
  • 失败定义:nonce 冲突 / DLQ 进入率 > 1%

开奖回调 DRAW CALLBACK

  • 场景:50 个活动同时到截止 → 50 个 VRF 请求并发
  • 目标:全部 ≤ 6 个区块完成回调
  • 工具:Foundry script + 监听 fulfillRandomWords
  • 失败定义:任何活动超时 / 回调丢失
SECTION 07 · CI GATES

CI / 发布门槛 CI & RELEASE GATES

每个阶段必须满足下面的硬性条件才允许进入下一阶段。必须项目失败直接卡住,推荐项目走 PR review。

PR open
静态检查 · checkstyle / spotbugs / detekt 全过 · gitleaks 无新泄露 · 协议: 任何依赖更新需 SBOM diff review
REQUIRED
PR merge
测试 · 单元 + 契约 + 集成全绿 · 行覆盖率不低于服务底线(见 SECTION 02)· FeignClientSurfaceTest 锁定 11 个
REQUIRED
staging
E2E + 性能 · 6 个 E2E 流程全过 · k6 压测 3 个场景全过 · BSC Testnet + TRON Nile 各跑 1 轮归集+提现
REQUIRED
staging
渗透 + 安全扫描 · OWASP ZAP baseline · trivy 镜像扫无 HIGH 及以上 · 内部安全 review 签字
ADVISORY
release
人工探索 + 回归 · 5 个 admin 后台关键页签字 · 应急预案演练通过 · 灰度回滚脚本就绪
REQUIRED
SECTION 08 · TEST DATA

测试数据与 Mock 策略 DATA & MOCKING

真实组件 REAL DEPENDENCIES

  • MySQL:Testcontainers 起 8.0,每个测试类独立 schema
  • Redis:Testcontainers 起 7.x,FLUSHDB 隔离
  • Kafka:Testcontainers KRaft 模式 + auto-topic
  • chain RPC:E2E 用真 BSC Testnet / TRON Nile

Mock 边界 WHAT TO MOCK

  • 外部 OAuth:TG bot API 用 WireMock,固定 hash 计算
  • KMS:本地 keystore 替代,签名算法不变
  • 风控外部源:OFAC 黑名单本地文件版本固化
  • 邮件 / 推送:不发实际,断言入队

种子数据 SEED DATA

  • 用户:固定 5 个 fixture user,涵盖新人/老用户/封号/KYC 完成/未完成
  • 钱包:HD 派生固定 path,确定性地址,跨测试可复用
  • 活动:3 个活动 fixture,售罄 / 进行中 / 已开奖
  • 历史订单:5 个订单,覆盖 PAID / REFUNDED / WIN / LOSE 各状态

禁忌 DO NOT

  • 不用生产数据做测试,任何脱敏都不允许
  • 不在 unit test 里碰真 DB / 真 Redis(用 in-memory 不算)
  • 不在 E2E 里用 mock chain(必须真 testnet)
  • 不在 CI 里跑 manual / 探索测试
SECTION 09 · DEFECT TRIAGE

缺陷分级与 SLA SEVERITY & SLA

发现缺陷后填 issue,按下表分级。SLA 是从分级到修复 PR 提交的时间,不是合并时间。

P0 · BLOCKER
资金损失 / 私钥风险 / 全站不可用 / 安全漏洞被利用。例:余额穿透,签名服务 RCE,全部活动开奖卡死。
SLA: ≤ 4h
P1 · CRITICAL
核心流程部分用户受影响,有手动 workaround。例:某条链下单失败但其它链正常,部分提现进 DLQ。
SLA: ≤ 1d
P2 · MAJOR
非核心流程/边界场景出错,不影响资金。例:admin 后台某筛选不工作,某些时区时间显示错。
SLA: ≤ 1w
P3 · MINOR
UI 瑕疵 / 文案 / 不影响功能。例:按钮颜色不对,空状态文案重复。
SLA: ≤ 1mo

QA 测试方案 V1.0 · 与 backend / frontend / contract 同步演进。
具体用例数、当前覆盖率、上一轮压测报告由 CI 自动统计,不在本页固化。