# SmartFarm V1 测试目录与固定 Fixture 状态:`开发前设计基线,尚未创建测试工程、执行测试或产生通过结论` 本文档把 [22-v1-test-acceptance-release-manual-plan.md](22-v1-test-acceptance-release-manual-plan) 中的领域场景转为可实施的测试注册规范,并补齐权限、幂等、并发、事件任务、普通商城回归、性能、UAT 和恢复演练编号。业务规则以 `12~14` 为准,写操作以 `31` 为准,事件任务以 `32` 为准,状态竞态以 `33` 为准。 当前冻结基线: - `90` 张农业扩展表。 - `108` 个 P0 页面追踪对象。 - `242` 个唯一写操作,对应 `242` 条自动契约元测试。 - `104` 个唯一领域事件、`114` 条事件生产映射。 - `48` 个唯一 Job,其中 `40` 组 Timer/Job、`8` 个仅事件触发 Job。 - `22` 中有 `323` 个 case-like 唯一编号:`316` 个测试 `case_id`、`7` 个 `G5-*` 工具/门禁决策编号。 - 本文保留 `89` 个平台通用测试场景,并新增 `16` 个不与 `22` 重复的补充专项场景。 - 领域专用稳定 `case_id` 合计 `421 = 316 + 89 + 16`。 - 顶层测试登记项合计 `663 = 242` 条写操作契约元测试 `+ 421` 条领域专用测试。 `90/104/48/108` 是必须全量覆盖的对象集合,不重复计入 `663`;它们会生成表、事件、Job 和页面执行实例。数量只用于审计,不代表已经执行或通过。新增需求必须新增编号或明确替代关系,不允许复用旧编号表达不同预期。 ## 一、编号与证据规则 ### 1. 稳定编号 | 对象 | 格式 | 示例 | | --- | --- | --- | | 测试场景 | `--NNN` | `CW-PICKUP-003` | | 执行实例 | `____` | `CW-SET-PP-003__UT__LR3` | | 写操作契约实例 | `OP::::` | `OP::CW_PICKUP_VERIFY::IDEM_SAME` | | 事件契约实例 | `EVT::::::` | `EVT::farm.animal.imported::ANIMAL_IMPORT_CONFIRM::CONSUME_IDEM` | | Job 契约实例 | `JOB::::` | `JOB::CloudPickupOverdueJob::SELECTOR_BOUNDARY` | | 表结构契约实例 | `TABLE::::` | `TABLE::eb_farm_cloud_supply_return::INDEX` | | Fixture | `FX---V` | `FX-CW-SETTLEMENT-GOLDEN-V1` | | 测试运行 | `RUN---` | `RUN-SIT-20260801T020000-a1b2c3d` | | 缺陷 | `BUG--NNN` | `BUG-RUN-SIT-20260801T020000-a1b2c3d-001` | 已有 `case_id` 永不改义。规则变化时新增用例并把旧用例标记为 `superseded_by`,不得删除历史执行证据。 ### 2. 数量复核口径 | 对象 | 主数据来源 | 当前数 | 机器复核规则 | | --- | --- | ---: | --- | | 农业表 | `15`、`34` | `90` | 提取 `eb_farm_[a-z0-9_]+` 去重,两文档集合必须相等 | | 写操作 | `31` | `242` | 只提取首列匹配 `^[A-Z][A-Z0-9_]+$` 的操作表行;行数、唯一数均为 `242` | | 领域事件 | `32` | `104` | 提取 `farm.[a-z0-9_.]+` 去重;生产映射表共有 `114` 行,允许同一事件由多个合法操作产生 | | Job | `32` | `48` | Job 文件名去重;`25` 个云仓 Timer Job、`15` 个农业/履约/基础 Timer Job、`8` 个事件 Job | | case-like 编号 | `22` | `323` | 提取表格首列;编号允许 `CW-ACT-009A` 这类三位数字后的字母后缀 | | 测试用例 | `22` | `316` | 从 `323` 中排除 `G5-001~007`;G5 是工具/执行门决策,不生成领域用例 | | G5 门禁决策 | `22` | `7` | 单独进入 `registry/gates.json`,验证配置是否遵守,不进入 `domain-cases.json` | | 平台通用用例 | 本文第八节 | `89` | 表首列去重;`12+8+12+10+12+12+7+8+8` | | 补充专项用例 | 本文第九节 | `16` | 表首列去重;`3+1+1+2+3+6`;不得重复登记 `22` 已有的 29 条新增专项用例 | 任何集合缺项、重项、计数漂移或主文档之间集合不一致,测试基线校验直接失败,不得用手工修改统计数字绕过。 ### 3. 测试层级 | 层级 | 含义 | 主要工具 | | --- | --- | --- | | `UT` | 金额、数量、状态和策略纯逻辑 | PHPUnit 9.6、Jest | | `DB` | Repository、锁、索引、事务和逻辑外键 | PHPUnit 9.6 + 独立测试库 | | `API` | HTTP 契约、权限、幂等和错误码 | Playwright APIRequestContext + Ajv | | `EVT` | Outbox、消费者、队列 Job 和定时监听器 | PHPUnit + 受控队列适配器 | | `COMP` | 前端组件和页面状态 | 现有 Jest、Vue Test Utils | | `E2E` | 四端浏览器/H5 主流程 | Playwright 1.52.0 | | `REG` | CRMEB 原商品、营销、订单、财务回归 | API + Playwright | | `PERF` | 并发、容量和恢复吞吐 | `grafana/k6:2.0.0` | | `UAT` | 分角色业务验收 | 脚本化人工验收 | | `DR` | 发布、停用、回退和恢复演练 | Runbook + 自动校验 | 微信小程序关键流程使用开发者工具和真机清单,不把 H5 通过等同于小程序通过。 ### 4. 每条测试的必需元数据 ```text case_id title requirement_ids[] decision_ids[] page_ids[] operation_codes[] api_contracts[] tables[] events_or_jobs[] layers[] fixture_ids[] preconditions steps assertions negative_assertions cleanup evidence owner_role status ``` `assertions` 必须同时覆盖 API、主事实、流水、Outbox、消费结果和最终投影中的适用项;只断言页面提示不算资金或库存用例通过。 ## 二、测试工程边界 开发阶段目录冻结为: ```text smartfarm/tests/ Unit/Farm/ Integration/Farm/ Contract/Farm/Generated/ Fixtures/Farm/ bootstrap.php phpunit.xml smartfarm_admin/tests/unit/farm/ smartfarm_mer/tests/unit/farm/ smartfarm_service/tests/unit/farm/ smartfarm_qa/ package.json package-lock.json playwright.config.ts ajv/ fixtures/ registry/domain-cases.json registry/gates.json registry/write-operations.json registry/events.json registry/jobs.json registry/tables.json registry/pages.json tests/contracts/ tests/api/ tests/e2e/admin/ tests/e2e/merchant/ tests/e2e/service/ tests/e2e/user-h5/ regression/ performance/ uat/ recovery/ artifacts// ``` 约束: 1. `smartfarm_qa` 使用 Node.js 18+、`@playwright/test@1.52.0` 和 `ajv@8.17.1`。 2. 后端使用 `phpunit/phpunit:^9.6`,实际版本由未来 `composer.lock` 固定。 3. 测试凭据、支付沙箱密钥和第三方 Key 只来自环境变量或 CI Secret,不进入仓库、截图和报告。 4. DEV/SIT 只能使用专用测试库、测试 Redis DB、测试队列前缀和测试文件目录。 5. 任何自动清理必须同时校验环境标识和 `run_id` 前缀,禁止在共享演示库或生产库执行清空。 ## 三、Fixture 生命周期 ### 1. 固定时钟与地域 - 业务时区固定为 `Asia/Shanghai`。 - 默认测试时钟为 `2026-08-01 10:00:00`。 - 自然日计算不含事实发生当日,次日为第 1 天,第 N 天截止 `23:59:59`。 - 需要测试真实计时器时,使用可注入 Clock 或推进测试时钟,不用长时间 `sleep`。 - 金额使用分或定点字符串,比例使用基点,禁止二进制浮点作为断言来源。 ### 2. 创建、隔离与清理 | 层级 | 建立方式 | 清理方式 | | --- | --- | --- | | `UT` | 内存对象/固定 JSON | 进程退出 | | `DB` | 每例事务或独立 schema | 回滚事务或删除该 `run_id` | | `API/EVT` | API/Fixture Loader 建立真实关系 | 按依赖逆序清理本次 `run_id` | | `E2E/UAT` | 预置版本化基线,再建立运行数据 | 保留审计证据,清理可重建测试数据 | | `PERF/DR` | 独占环境快照 | 整体恢复快照并运行 `verify_after` | 账本、支付回调、库存和回购用例不得通过直接修改最终余额来准备前置条件,应通过受控 Fixture Loader 或明确的非生产支付适配器生成业务事实。 ## 四、固定角色与数据范围 ### 1. 角色 Fixture | Fixture | 角色 | 固定范围 | | --- | --- | --- | | `FX-BASE-ACTOR-V1` | 超级管理员、农业运营、云仓运营、财务、客服主管、仓储主管 | 按测试用例分配 `all` 或显式对象范围 | | `FX-MERCHANT-A-B-V1` | 商户 A、商户 B 及各自管理员/员工 | A/B 商品、供货、订单和账本严格隔离 | | `FX-SERVICE-A-B-V1` | 客服 A、现场人员 A、仓储人员 A、越界人员 B | 农场、仓库、自提点、任务和职责范围隔离 | | `FX-USER-U123-V1` | U1、U2、U3 | 持仓比例 `40/35/25`,各自地址和权益隔离 | | `FX-SCOPE-VERSION-V1` | 同一管理员的启用、停用、重新启用范围和两版集合 | 验证 `scope_set_version`、唯一行复用、并发保存和审计差异 | 账号使用合成数据,不复用真实用户手机号、邮箱、密码或身份证件。 ### 2. 权限通过线 - 列表先套用范围再分页。 - 按 ID 越界统一返回 `COMMON_NOT_FOUND`。 - 对象可见但动作无权返回端侧稳定权限错误。 - 前端 `allowed_actions` 只负责显示,后端每次写入重新校验。 - PII、导出、账本审核、回购和异常最终方案使用独立权限。 ## 五、领域 Fixture 目录 | Fixture | 核心数据 | 主要覆盖 | | --- | --- | --- | | `FX-REGISTRY-SNAPSHOT-V1` | `90` 表、`242` 操作、`104` 事件、`114` 生产映射、`48` Job、`108` 页面清单及来源哈希 | 集合相等、重复项和统计漂移 | | `FX-CW-SUPPLY-V1` | 商户单 SKU 供货、批准预留、部分送达、待检、拒收和短缺 | `CW-SUP-001~015` | | `FX-CW-PLATFORM-SUPPLY-V1` | `is_trader=1` 自营来源、普通商户来源、来源 SKU 最后一份可售库存 | `CW-SUP-016~017`、`CW_PLATFORM_SUPPLY_CREATE` | | `FX-CW-SUPPLY-DISPOSAL-V1` | 两条独立退回、两条承接预案、制单/复核人、目标自营 SKU、处置数量竞争 | `CW-SUP-018~022`、退回/承接实体和三段式 | | `FX-CW-MERCHANT-FULFILLMENT-V1` | 商户 A/B 责任快照、已发包裹、补充证据、售后退回在途和差异数量 | `CW-MFUL-001~004`、三项新增商户履约操作 | | `FX-CW-ACTIVITY-LIFECYCLE-V1` | 草稿、预热、进行中、结束、未支付释放和库存闭合 | `CW-ACT-*` | | `FX-CW-MODE-A-V1` | 到期统一结算活动 SKU/批次 | `CW-SET-F-*` | | `FX-CW-MODE-B-V1` | 分期收益、到期本金活动 SKU/批次 | `CW-SET-PF-*` | | `FX-CW-MODE-C-V1` | 分期本金收益活动 SKU/批次 | `CW-SET-PP-*` | | `FX-CW-SETTLEMENT-GOLDEN-V1` | 100 件、U1/U2/U3 为 `40/35/25` | 三种结算和逆向调整 | | `FX-CW-PICKUP-PARTIAL-V1` | 10 件自提,已核销 7 件、剩余 3 件逾期;延期/改寄/退款/回购建议与用户确认版本 | `CW-PICKUP-*`、`PICKUP-REC-*` | | `FX-CW-FREIGHT-RACE-V1` | 去向截止、运费超时、迟到支付和退款 | `CW-FREIGHT-*` | | `FX-CW-MATURITY-V1` | 到期 70%、30 日在途宽限、90% 回购 | `CW-BUY-*` | | `FX-AG-LAND-V1` | 整块/面积份额、正常、延期、减产和绝收 | `LAND-*` | | `FX-AG-ADOPTION-V1` | 单体/批次份额、死亡、等价和非等价替换 | `ADOPT-*` | | `FX-AG-REFUND-V1` | 服务价值、交付价值、分批未履约退款 | `LAND-EX-*`、`ADOPT-EX-*` | | `FX-AG-FULFILLMENT-V1` | 多次产出、地址版本、分包、运费和售后 | `FUL-*` | | `FX-PRODUCT-MATERIAL-EXPIRY-V1` | 同一已批准商品的三份当前必需材料,分别处于有效、7 天预警和到期;另有新材料集版本 | `MAT-001~004`、全量资格重算 | | `FX-ANIMAL-IMPORT-V1` | `1000` 行合法文件、`1001` 行文件、逐行错误文件、同内容不同哈希、目标栏舍版本和容量冲突 | `ANIMAL-IMPORT-*`、`farm.animal.imported` | | `FX-ATTACHMENT-ID-DOMAINS-V1` | 可见/跨商户/已删除的系统附件与现场证据附件;两个表故意准备相同数字主键 | `ATTACH-001~002`、异步结果文件和所有材料/证据 DTO | | `FX-TRACE-VERSION-V1` | 草稿、审核、发布、撤回、材料到期和稳定公开码 | `TRACE-*` | | `FX-ASYNC-OPERATION-V1` | 排队、执行中、部分失败、成功、失败、租约过期和结果文件操作 | `ASYNC-*`、四端操作详情 | | `FX-TIMER-BOUNDARY-V1` | 每个 Timer 选择器各有 `due_at < now`、`= now`、`> now`、错误状态和同值相邻 ID | `TIMER-*`、`JOB-*` | | `FX-ASYNC-FAILURE-V1` | 重复事件、游标中断、租约过期、最终失败 | `EVT-*`、`JOB-*`、重放与恢复 | | `FX-CRMEB-REG-V1` | 未映射普通商品、普通营销、优惠、订单、售后和财务 | `REG-*` | | `FX-PERF-LARGE-V1` | 10 万持仓、10 个可分配批次、1 万 Outbox 积压 | `PERF-*` | 附件 Fixture 固定两个互不替代的 ID 域: | ID 域 | 物理来源 | 允许用途 | 必测拒绝 | | --- | --- | --- | --- | | 系统附件 ID | `eb_system_attachment.attachment_id` | 商品农业资料、供货/溯源材料、导入源文件、异步结果文件 | 跨商户、已删除、用途不符、提交现场证据 ID | | 农业证据附件 ID | `eb_farm_evidence_attachment.attachment_id`,DTO 语义名 `farm_evidence_attachment_id` | 现场过程、产出、履约、异常的临时上传与正式绑定 | 跨服务账号/范围、已绑定到其他对象、提交系统材料 ID | 即使两个表存在相同数字主键,也必须按 DTO 字段和目标 Repository 解析,禁止“先查到哪个表就用哪个”。API 返回时保留不同字段名,不能统一成含义不明的 `attachment_id`。 ### 专项覆盖追踪 | 专题 | 领域用例 | 写操作 | 数据、事件或 Job | | --- | --- | --- | --- | | 统一异步操作 | `ASYNC-001~006` | 所有返回 `202` 的操作及其原操作码 | `eb_farm_async_operation`、四端 `operation/detail`、租约/结果文件 | | 平台自营供货 | `CW-SUP-016~017` | `CW_PLATFORM_SUPPLY_CREATE` | `eb_farm_cloud_supply`、库存流水、`farm.cloud.supply.approved` | | 供货实物退回 | `CW-SUP-018`、`CW-SUP-011` | `SYS_CW_INVENTORY_CLOSE`、`CW_SUPPLY_RETURN_ACK`、`CW_SUPPLY_RETURN_COMPLETE` | `eb_farm_cloud_supply_return`、`farm.cloud.supply.return_pending`、`farm.cloud.supply.returned` | | 平台承接三段式 | `CW-SUP-019~022` | `CW_SUPPLY_ACQUIRE_PREPARE`、`CW_SUPPLY_ACQUIRE_REVIEW`、`CW_SUPPLY_ACQUIRE_EXECUTE` | `eb_farm_cloud_supply_acquisition`、`farm.cloud.supply.platform_acquired` | | 材料到期全量重算 | `MAT-001~004` | `PRODUCT_MATERIAL_EXPIRY_APPLY` | 商品 profile/材料、`farm.product.material.expiring`、`farm.product.material.expired`、`ProductMaterialExpiryJob` | | 管理员范围重启用 | `SCOPE-001~004`、`SEC-012` | `FARM_ADMIN_SCOPE_SAVE` | `eb_farm_admin_scope`、审计、`farm.admin.scope.changed` | | 动物三段导入 | `ANIMAL-IMPORT-001~006` | `ANIMAL_IMPORT_VALIDATE`、`ANIMAL_IMPORT_CONFIRM` | 异步操作、动物/容量/Outbox、`farm.animal.imported`、两个导入 Job | | 精确 Timer 选择器 | `TIMER-001~008` | 对应 `SYS_*` 内部操作 | `32` 的 40 组 Timer/Job,重点选择器见第十一节 | | 商户履约补证/退货/异常 | `CW-MFUL-001~004` | `CW_FULFILLMENT_LOGISTICS_UPDATE`、`CW_FULFILLMENT_EVIDENCE_ADD`、`CW_FULFILLMENT_RETURN_RECEIVE`、`FARM_EXCEPTION_CREATE` | 履约/包裹/退回/异常、系统附件和责任快照 | | 自提逾期建议 | `CW-DISP-011`、`CW-PICKUP-003~004`、`PICKUP-REC-001~006` | `FARM_EXCEPTION_PROPOSE`、`CW_PICKUP_OVERDUE_RESOLVE` | 自提、异常/方案/确认、`CloudPickupOverdueJob` | | 双附件 ID 域 | `ATTACH-001~002` | `FARM_ATTACHMENT_UPLOAD` 及所有材料/证据写操作 | `eb_system_attachment`、`eb_farm_evidence_attachment`、`result_file_id` | ## 六、固定金额与数量算例 ### 1. 云仓结算主例 ```text 批次数量 100 件 用户本金单价 10.00 元 二次有效售价 14.00 元 用户利润分成率 70% U1/U2/U3 持仓 40/35/25 件 100% 确认销售额 1,400.00 已售本金 1,000.00 利润池 400.00 用户可分利润 280.00 用户本金和收益合计 1,280.00 U1/U2/U3 累计 512.00/448.00/320.00 ``` 从已结 `75%` 回退到真实 `70%`: | 模式 | 批次累计差额 | U1/U2/U3 | | --- | ---: | --- | | A 到期统一结算 | `0.00` | `0/0/0` | | B 分期收益、到期本金 | `-14.00` | `-5.60/-4.90/-3.50` | | C 分期本金和收益 | `-64.00` | `-25.60/-22.40/-16.00` | 正常退款先抵扣未入账和同持仓未来应付,最终不足记平台风险,不直接扣用户可用余额。 ### 2. 到期回购 真实销售 `70` 件、未售 `30` 件、回购率 `90%`: ```text 回购金额池 = 30 × 10.00 × 90% = 270.00 元 U1/U2/U3 未售等价量 = 12/10.5/7.5 U1/U2/U3 回购金额 = 108.00/94.50/67.50 ``` 批次先形成金额池,再按持仓最大余数法分到分。 ### 3. 分钱尾差 `1.00` 元按 `1:1:1` 分配为 `0.34/0.33/0.33`;余数相同时由最小 `holding_id` 取得多出的 1 分。重跑必须得到完全相同结果。 ### 4. 农业未履约退款 ```text 实付金额 900.00 生产服务价值 270.00 交付退款基数 630.00 承诺数量 30 累计退款 7 件 147.00 累计退款 13 件 273.00 第二次本次应退 126.00 ``` 公式为 `交付退款基数 × 累计未履约退款数量 ÷ 承诺数量 - 历史已退 - 处理中退款`。 ### 5. 短缺和部分提货 - 未履约需求 `5/3/2`,可分配 `7` 件,最大余数结果为 `4/2/1`;余数再相同时按 `paid_at`、`order_id`。 - 云仓自提 10 件,先核销 4 件、再核销 3 件,剩余 3 件;每次生成不可变核销事实,只有全部闭合才完成整条明细。 ## 七、22 的 316 个测试用例与 7 个门禁决策 `22` 表格首列当前共有 `323` 个 case-like 唯一编号。注册规则把 `G5-001~007` 识别为工具/执行门决策并写入 `registry/gates.json`,其余 `316` 个才写入 `registry/domain-cases.json`。测试用例分布如下: | 前缀 | 数量 | 前缀 | 数量 | | --- | ---: | --- | ---: | | `CW-*` | 159 | `LAND-*` | 16 | | `ADOPT-*` | 14 | `FUL-*` | 7 | | `MER-SET-*` | 14 | `PROD/OUTPUT/TRACE-*` | 10 | | `SVC-*` | 32 | `MAP-*` | 18 | | `PAGE-*` | 11 | `DEFAULT-*` | 11 | | `DB-REF-*` | 4 | `ATTACH-*` | 2 | | `ANIMAL-IMPORT-*` | 4 | `ASYNC-*` | 3 | | `MAT-*` | 3 | `SCOPE-*` | 3 | | `TIMER-*` | 5 | | | 测试 `case_id` 校验总数:`316`。其中 `CW-SUP-016~022`、`CW-MFUL-001~004`、`MAT-001~003`、`SCOPE-001~003`、`ANIMAL-IMPORT-001~004`、`ASYNC-001~003`、`TIMER-001~005` 和 `ATTACH-001~002` 是当前技术审计新增的 `31` 条专项用例。实现时 Markdown、`domain-cases.json` 和 `gates.json` 的分类、数量或集合不一致即阻断测试发布。 特别断言: 1. 普通用户租地和认养的产出履约只有邮寄。 2. 自提和代销只属于云仓首次购买去向。 3. 商户端导航配置商品、供货、履约责任和货款;租地/认养参与入口配置在用户端。 4. 普通秒杀与云仓活动可复用交互模式,但库存、订单、结算和状态完全隔离。 5. `system_attachment_id` 与 `farm_evidence_attachment_id` 永不互换;相同数字主键也必须按 ID 域拒绝串读。 ## 八、89 个平台级测试场景 ### 1. 权限与安全 `SEC-001~012` | case_id | 场景 | 核心预期 | | --- | --- | --- | | `SEC-001` | 角色菜单可见性 | 只显示角色授权页面,直接输入 URL 仍由后端拒绝 | | `SEC-002` | 对象可见但动作无权 | 返回稳定权限错误,页面不显示命令按钮 | | `SEC-003` | 列表对象范围 | 先按范围过滤再分页,合计数不泄露越界对象 | | `SEC-004` | 按 ID 越界 | 统一 `COMMON_NOT_FOUND` | | `SEC-005` | PII 默认投影 | 手机、地址和证件默认脱敏,查看完整信息单独审计 | | `SEC-006` | 导出权限 | 无独立导出权限不能创建任务,有权导出记录范围与下载审计 | | `SEC-007` | 附件绑定越界 | 临时附件只能绑定同账号、同范围、同业务对象 | | `SEC-008` | 二维码伪造/过期 | 验签失败或过期不返回内部对象详情 | | `SEC-009` | Token 失效与重放 | 失效 Token 不可写入,重新登录后旧请求不自动执行 | | `SEC-010` | 地图和第三方密钥 | 服务端 Key/SK 不出现在响应、日志或前端产物 | | `SEC-011` | 日志与事件脱敏 | 不记录 Token、完整地址、支付密钥和完整规则 JSON | | `SEC-012` | 权限范围版本变化 | 旧 `scope_set_version` 触发上下文刷新,不能扩大权限 | ### 2. 幂等 `IDEM-001~008` | case_id | 场景 | 核心预期 | | --- | --- | --- | | `IDEM-001` | 同请求串行两次 | 返回首次业务结果 | | `IDEM-002` | 同请求并发 10 次 | 仅一个业务事实和一组副作用 | | `IDEM-003` | 同幂等键不同摘要 | 返回 `COMMON_IDEMPOTENCY_CONFLICT` | | `IDEM-004` | 服务端成功后客户端超时重试 | 不重复库存、账本、通知或任务 | | `IDEM-005` | 事务回滚后原键重试 | 不留半成品,原键可成功 | | `IDEM-006` | 支付/退款回调重复 | 按业务单号和渠道事实只确认一次 | | `IDEM-007` | Job 同结果键重跑 | 只产生一个确定性业务结果 | | `IDEM-008` | 同事件重复消费 | 消费日志和业务唯一键双重防重 | ### 3. 并发竞态 `CONC-001~012` | case_id | 并发场景 | 核心预期 | | --- | --- | --- | | `CONC-001` | 活动 SKU 最后一份库存 | 不超卖、不重复订单 | | `CONC-002` | 两次供货审核预留同一来源库存 | 来源预留不超过可用量 | | `CONC-003` | 用户确认去向与超时任务 | 只形成一个最终去向 | | `CONC-004` | 运费成功回调与超时任务 | 邮寄或超时分支唯一,迟到款全额退款 | | `CONC-005` | 自提核销与逾期处理 | 已核销量保留,剩余量只进入一种方案 | | `CONC-006` | 二次分配与普通订单取消 | 分配生效或释放一次 | | `CONC-007` | 二次退款与观察期生效 | 有效销售净额和进度唯一 | | `CONC-008` | 节点结算与退款回退 | 按同一计算版本串行,不覆盖历史账本 | | `CONC-009` | 到期回购与最后一笔二次销售 | 所有权切割后数量和风险归属唯一 | | `CONC-010` | 正式入账与余额支付/充值 | 行锁串行,不丢更新、不超扣 | | `CONC-011` | 地块最后容量确认 | 仅一个有效占用,另一个明确冲突 | | `CONC-012` | 认养单体/份额最后容量确认 | 单体唯一、份额和预留总量不超容量 | ### 4. 事件可靠性 `EVT-001~010` | case_id | 场景 | 核心预期 | | --- | --- | --- | | `EVT-001` | 业务事务回滚 | 不留下可投递 Outbox | | `EVT-002` | 事务提交 | 事实与 Outbox 同时可见 | | `EVT-003` | 至少一次投递 | 丢唤醒后扫描仍可投递 | | `EVT-004` | 重复消费 | 不重复业务结果 | | `EVT-005` | 乱序事件 | 按版本拒绝或等待前置事实 | | `EVT-006` | 事件 schema 版本 | 兼容版本可消费,不兼容进入明确失败 | | `EVT-007` | payload 最小化 | 不复制 PII、完整地址和大规则快照 | | `EVT-008` | 人工重放 | 使用原事件和结果键,保留重放审计 | | `EVT-009` | 最终失败 | 进入失败记录、冻结影响对象并告警 | | `EVT-010` | 对账补事实 | 只补缺失事件/投影,不制造重复账本 | ### 5. Job 与 Timer `JOB-001~012` | case_id | 场景 | 核心预期 | | --- | --- | --- | | `JOB-001` | 游标分页遇到新增数据 | 不跳过、不无限回扫 | | `JOB-002` | 同业务键争抢租约 | 只有一个执行者 | | `JOB-003` | 执行中进程退出 | 租约到期后按原键恢复 | | `JOB-004` | 多分片并行 | 分片互斥且结果全集完整 | | `JOB-005` | 可重试错误 | 按 10 秒、1 分、5 分、15 分、1 小时退避 | | `JOB-006` | 不可重试错误 | 直接人工复核,不消耗无限重试 | | `JOB-007` | Timer 多实例 | 只有一实例取得调度锁,业务仍由队列 Job 执行 | | `JOB-008` | 四队列隔离 | 财务、关键交易不被通知/报表积压阻塞 | | `JOB-009` | 队列背压 | 产生积压告警,不绕过幂等或调高无界并发 | | `JOB-010` | 人工预演重放 | 先显示影响,再授权执行,保留操作审计 | | `JOB-011` | 到期宽限最终化 | 只写一次所有权切割和待审回购预案 | | `JOB-012` | 异常确认超时 | 等价方案按快照接受,其余默认拒绝并转退款 | ### 6. CRMEB 回归 `REG-001~012` | case_id | 场景 | 核心预期 | | --- | --- | --- | | `REG-001` | 普通商品增删改、规格和库存 | 与基线一致 | | `REG-002` | 普通秒杀、拼团、预售、助力、积分商品 | 不触发云仓状态或批次 | | `REG-003` | 平台券、商户券、会员价和积分抵扣 | 普通商品承担规则不变 | | `REG-004` | 购物车失效和多商户拆单 | 普通分组逻辑不变 | | `REG-005` | 普通订单确认、支付、取消、发货、核销和收货 | 未绑定订单走原策略 | | `REG-006` | 普通未发货/退货/部分退款 | 原商户财务、库存和优惠恢复正确 | | `REG-007` | 普通运费、快递、自提和电子面单 | 不进入农业履约表 | | `REG-008` | 商户普通账单、冻结、提现和权限 | 与云仓供货结单隔离 | | `REG-009` | 用户充值、余额支付、退款和余额流水 | 与农业正式入账并发不丢更新 | | `REG-010` | 原客服会话和订单上下文 | `/kefu/dashboard` 行为不变 | | `REG-011` | 未映射 SKU 性能 | 不新增农业查询或锁 | | `REG-012` | 智慧农业全部入口关闭 | 普通商城仍可完整交易 | ### 7. 性能 `PERF-001~007` | case_id | 固定负载 | 通过线 | | --- | --- | --- | | `PERF-001` | 云仓浏览 300 VU、10 分钟 | P95 ≤ 500ms,P99 ≤ 1s,错误率 < 0.2% | | `PERF-002` | 单 SKU 100 并发、100 RPS、5 分钟 | P95 ≤ 800ms,P99 ≤ 1.5s,超卖/重复订单为 0 | | `PERF-003` | 支付/退款 50 并发、同事实重复 10 次 | P95 ≤ 500ms,唯一业务结果为 1 | | `PERF-004` | FEFO 100 并发、至少 10 批次 | P95 ≤ 800ms,数量守恒且无悬挂 | | `PERF-005` | 10 万持仓、4 节点结算 | 60 分钟内闭合,无重复账本 | | `PERF-006` | 1 万 Outbox/Job 积压恢复 | 15 分钟内清空,死信可定位 | | `PERF-007` | 10 万主记录列表和导出 | 首屏 P95 ≤ 1s,导出异步且不全量入内存 | ### 8. 恢复演练 `DR-001~008` | case_id | 演练 | 核心预期 | | --- | --- | --- | | `DR-001` | 数据库备份恢复 | 恢复点可用,`verify_after` 和五段对账通过 | | `DR-002` | 后端应用回退 | 旧版本可忽略扩展表,入口关闭后普通商城可用 | | `DR-003` | 队列停机与重放 | 恢复后按原幂等键清空积压 | | `DR-004` | Outbox 投递中断 | 事实不丢,恢复扫描后至少一次投递 | | `DR-005` | 重复/迟到支付退款回调 | 最终状态唯一,迟到款按规则退款 | | `DR-006` | `M01~M12` 中途失败 | 可判定已完成步骤,重复执行安全或明确停止 | | `DR-007` | 前端制品/CDN 回退 | 版本一致、缓存可控,不与新 API 产生危险写入 | | `DR-008` | 农业停用后的普通商城确认 | 商品、营销、下单、支付、退款和客服冒烟通过 | ### 9. UAT `UAT-001~008` | case_id | 角色流程 | 通过条件 | | --- | --- | --- | | `UAT-001` | 平台管理员建农场、套餐、活动和规则 | 发布预检、权限和审计符合规格 | | `UAT-002` | 商户商品供货、送达、对账和货款 | 只见本商户数据,货款条件解释一致 | | `UAT-003` | 用户云仓抢购、稍后选择、三去向和持仓 | 页面状态与账本一致 | | `UAT-004` | 用户租地、分配、过程、产出邮寄 | 不出现自提或代销 | | `UAT-005` | 用户认养、替换、产出邮寄和异常确认 | 权益、确认和退款可理解 | | `UAT-006` | 客服/现场任务、扫码、证据、核销和草稿 | 范围隔离、离线草稿和提交恢复可用 | | `UAT-007` | 财务结算、回购、冲正和五段对账 | 金额可追溯,异常不得直接改余额 | | `UAT-008` | 跨端异常上报、审核、用户确认和执行 | 同一事实链在四端状态一致 | ## 九、16 个补充专项场景 本节只补 `22` 新增 29 条专项用例尚未覆盖的风险,不重复登记平台自营供货、退回/承接、三项商户履约、材料全量重算、范围重启用、动物导入基础流程和 Timer 字段口径。 ### 1. 异步操作恢复 `ASYNC-004~006` | case_id | 优先级 | 场景 | 核心断言 | Fixture | | --- | --- | --- | --- | --- | | `ASYNC-004` | P0 | 同一业务命令和 `request_id` 重复受理 | 返回同一 `operation_no`;不得建立第二条异步操作、Job 或结果文件 | `FX-ASYNC-OPERATION-V1` | | `ASYNC-005` | P0 | 执行进程在进度提交前退出、租约到期后恢复 | 原结果键继续执行,进度只单调推进,成功/失败计数不重复累计 | `FX-ASYNC-OPERATION-V1` | | `ASYNC-006` | P1 | 终态操作被迟到 Job、重复回调或人工刷新触达 | 终态、`finished_at` 和结果摘要不可回退;敏感错误详情保持脱敏 | `FX-ASYNC-OPERATION-V1` | ### 2. 材料与范围竞态 `MAT-004`、`SCOPE-004` | case_id | 优先级 | 场景 | 核心断言 | Fixture | | --- | --- | --- | --- | --- | | `MAT-004` | P0 | 材料替换/重新审核与到期任务并发 | 锁商品和整套当前材料后只提交一个集合版本;资格取最终完整集合计算结果,历史快照不变 | `FX-PRODUCT-MATERIAL-EXPIRY-V1` | | `SCOPE-004` | P0 | 范围撤销/重启用与管理员写请求并发 | 变更提交后的下一请求立即按新集合鉴权;已进入事务的命令不被中途扩大范围,审计可关联集合版本 | `FX-SCOPE-VERSION-V1` | ### 3. 动物导入幂等与原子性 `ANIMAL-IMPORT-005~006` | case_id | 优先级 | 场景 | 核心断言 | Fixture | | --- | --- | --- | --- | --- | | `ANIMAL-IMPORT-005` | P0 | 同一确认操作并发或重复执行 10 次 | 只导入一批资产、写一组审计/Outbox,并只产生一次 `farm.animal.imported` 业务结果 | `FX-ANIMAL-IMPORT-V1` | | `ANIMAL-IMPORT-006` | P0 | 第 N 行发生容量冲突、唯一键冲突或数据库异常 | 全批动物、容量和关联记录均为零写入;原附件与校验结果可保留用于重新校验,不允许从失败行续写 | `FX-ANIMAL-IMPORT-V1` | ### 4. Timer 边界与租约 `TIMER-006~008` | case_id | 优先级 | 场景 | 核心断言 | Fixture | | --- | --- | --- | --- | --- | | `TIMER-006` | P0 | 对 `TIMER-001~005` 每个精确选择器测试截止前、等于截止、截止后和错误状态 | 仅 `due_at <= now` 且状态完全匹配的记录入选;不得用 `update_time`、相邻表状态或空截止时间推断 | `FX-TIMER-BOUNDARY-V1` | | `TIMER-007` | P0 | 同一截止时间跨两页并在扫描期间插入新记录 | 使用登记的“截止字段 + ID”游标,不漏、不重、不会无限回扫;下一轮可处理新到期记录 | `FX-TIMER-BOUNDARY-V1` | | `TIMER-008` | P0 | 多实例争抢同一批候选且在线命令同时改变状态 | 只有一个实例取得租约;单条处理前在锁内重查状态/版本,已不符合选择器的记录幂等跳过 | `FX-TIMER-BOUNDARY-V1` | ### 5. 自提逾期建议与处置 `PICKUP-REC-001~006` | case_id | 优先级 | 场景 | 核心断言 | Fixture | | --- | --- | --- | --- | --- | | `PICKUP-REC-001` | P0 | 自提到期任务命中未核销剩余量 | 只建立或关联协商异常,不自动改寄、退款、回购或代销;已核销量不变 | `FX-CW-PICKUP-PARTIAL-V1` | | `PICKUP-REC-002` | P1 | 服务人员提交延期、改寄、退款或回购建议 | 仅写建议版本和联系记录;请求不得携带最终金额、库存恢复量或最终去向 | `FX-CW-PICKUP-PARTIAL-V1` | | `PICKUP-REC-003` | P0 | 10 件中已核销 7 件后提出处置 | 方案只作用于剩余 3 件,四种完成数量之和与 `pickup_qty` 闭合 | `FX-CW-PICKUP-PARTIAL-V1` | | `PICKUP-REC-004` | P0 | 平台处理旧建议版本或过期用户确认 | 版本/确认失败且不写数量、运费单、退款或回购;刷新后返回当前允许动作 | `FX-CW-PICKUP-PARTIAL-V1` | | `PICKUP-REC-005` | P0 | 已确认方案执行延期、改寄、退款或异常回购 | 每次只允许一种方案生效;对应数量、资金、履约和商户资格事实可追踪且不重复 | `FX-CW-PICKUP-PARTIAL-V1` | | `PICKUP-REC-006` | P0 | 到期任务、服务建议和平台处置并发/重跑 | 一条主异常、版本化建议和一个最终处置;结果键相同返回首次结果,数量恒等式保持成立 | `FX-CW-PICKUP-PARTIAL-V1` | ## 十、242 个写操作的自动契约元测试 `31` 中每个唯一 `operation_code` 生成一条顶层元测试 `OP::`,各维度作为参数化子测试执行,不能只依赖所属流程的一个 E2E 用例,也不把 10 个维度机械统计成 10 条业务用例。 ### 1. 操作集合分布 | `31` 分组 | 数量 | | --- | ---: | | CRMEB 核心适配命令 | 6 | | 定时任务和事件消费者内部操作码 | 41 | | 商品资料与管理员范围 | 7 | | 活动和活动商品 | 13 | | 商户申请、交付、收货和验收 | 19 | | 云仓订单、去向、批次和回购 | 23 | | 财务、结单和对账 | 16 | | 农业主数据通用命令 | 35 | | 租地与认养套餐 | 10 | | 真实资源预留与确认 | 6 | | 生产批次、任务和过程记录 | 17 | | 产出与履约 | 20 | | 统一异常执行 | 10 | | 溯源 | 11 | | 服务/现场端专用命令 | 8 | | **合计** | **242** | 注册生成器必须验证表格行数和唯一集合同时为 `242`,所有操作码长度不超过 `32`,且每项都能解析出 HTTP 路由或明确的内部生产者。 ### 2. 参数化维度 | 维度 | 适用范围 | 断言 | | --- | --- | --- | | `REGISTRY` | 全部 | 操作码、入口、DTO、写集、事件、风险级和领域用例映射完整 | | `HAPPY` | 全部 | 合法输入产生唯一预期结果,响应字段与 `37` 一致 | | `VALIDATION` | 全部 | HTTP 请求校验字段;内部操作校验事实版本和结果键 | | `IDENTITY` | 全部 | HTTP 校验 Token/端身份;内部操作校验合法事件、Timer 或核心适配来源 | | `SCOPE` | 有业务对象范围时 | 列表/详情/写入均重新校验,越界不泄露 | | `STATE` | 全部 | 非法前置状态不写入,`allowed_actions` 与事实一致 | | `VERSION` | 有版本字段时 | 旧版本拒绝并返回当前摘要 | | `IDEM_SAME` | 全部 | HTTP 同键或内部结果键重跑返回首次结果 | | `IDEM_CONFLICT` | 全部 | 相同键不同输入摘要停止并告警,不覆盖首次事实 | | `ROLLBACK` | 事务写时 | 任一中间失败不留半成品 | | `OUTBOX` | 产生事件时 | 事实和 Outbox 同事务;回滚时两者均不可见 | | `ASYNC` | 返回 `202` 时 | 只建立一次 `eb_farm_async_operation`,响应和四端查询契约一致 | | `CONCURRENCY` | 资金/库存/容量/状态终结时 | 并发后恒等式与终态唯一 | | `PROJECTION_AUDIT` | 全部 | 主事实、流水、审计、列表、详情和通知投影不互相矛盾 | 不适用维度必须在注册表写明理由,不能用空测试伪装通过。 ### 3. 风险等级 | 等级 | 范围 | 最低层级 | | --- | --- | --- | | `W1` | 草稿、普通配置、备注 | `UT/API/COMP` | | `W2` | 发布、分配、履约、审核 | `UT/DB/API/EVT/E2E` | | `W3` | 支付、退款、库存、账本、回购、冲正 | `UT/DB/API/EVT/E2E/PERF/DR` | 三项新增商户履约操作固定映射: | 操作码 | 风险 | 领域用例 | 必测事实 | | --- | --- | --- | --- | | `CW_FULFILLMENT_LOGISTICS_UPDATE` | `W2` | `CW-MFUL-001` | 当前责任方、包裹版本、变更前后快照、已出库数量不变 | | `CW_FULFILLMENT_EVIDENCE_ADD` | `W2` | `CW-MFUL-002` | 附件归属、不可变追加、跨商户拒绝和审计 | | `CW_FULFILLMENT_RETURN_RECEIVE` | `W3` | `CW-MFUL-003` | 退回实收/短少/质量数量、待检或异常、不得直接恢复可售库存 | `FARM_EXCEPTION_CREATE` 的商户履约入口由 `CW-MFUL-004` 验证责任快照和禁止提交金额/库存结果。未来 `smartfarm_qa/registry/write-operations.json` 必须与 `31` 的 `242` 个操作码集合完全一致;缺少操作、重复操作、未分配风险等级、未声明不适用维度或无可执行实例均阻断 G5。 ## 十一、事件、Job、Timer 和四队列覆盖 ### 1. 104 个事件 | `32` 分组 | 唯一事件数 | 生产映射行 | | --- | ---: | ---: | | 商品农业资料与管理员范围 | 6 | 7 | | 活动与供货 | 12 | 14 | | 首次订单、去向和运费 | 15 | 16 | | 活动闭合、批次和二次零售 | 20 | 20 | | 用户与商户财务 | 10 | 12 | | 权益、资源分配和生产 | 20 | 23 | | 产出、履约、异常和溯源 | 21 | 22 | | **合计** | **104** | **114** | 同名事件由多个合法操作产生时,只保留一个事件 schema,但每条生产映射都生成 `EVT::::` 执行实例。每个事件至少验证: 1. 生产条件和事务回滚。 2. payload 最小字段及 schema 版本。 3. 消费者幂等和业务结果唯一键。 4. 乱序、重复和人工重放。 5. 最终失败、告警和对账修复。 供货退回/承接至少覆盖 `farm.cloud.supply.return_pending`、`farm.cloud.supply.returned`、`farm.cloud.supply.platform_acquired`;动物确认导入必须覆盖 `farm.animal.imported` 的单次生产、双消费者幂等和失败重放。 ### 2. 48 个 Job - 云仓 Timer/Job:`25`。 - 农业、履约和基础 Timer/Job:`15`。 - 仅事件触发 Job:`8`,包括动物校验/确认导入。 - 合计:`48` 个唯一 Job、`40` 组 Timer/Job。 每个 Job 至少验证: 1. 候选查询、索引条件、批次上限。 2. 游标推进和租约。 3. 中断恢复、重试和不可重试错误。 4. 与同业务对象在线命令并发。 5. 监控指标、失败记录和人工预演重放。 ### 3. 精确 Timer 选择器 | Timer/Job | 冻结选择器 | 专项用例 | | --- | --- | --- | | `CloudChoiceExpireJob` | 订单明细 `status in (paid_pending_choice,delivery_pending_freight)` 且 `choice_deadline_at <= now` | `TIMER-001` | | `CloudFreightExpireJob` | 运费单 `pay_status in (pending,paying)` 且 `expired_at <= now` | `TIMER-001` | | `CloudBatchStartJob` | 批次 `status=consign_ready` 且 `consign_start_at <= now` | `TIMER-002` | | `CloudResaleEffectiveJob` | 分配 `status=observing` 且 `observation_end_at <= now` | `TIMER-002` | | `CloudPickupOverdueJob` | **自提表** `status in (pending,partially_verified)` 且 `expires_at <= now` | `TIMER-003`、`PICKUP-REC-001` | | `FarmExceptionConfirmationExpireJob` | 方案版本 `status=pending_user_confirmation` 且 `confirmation_deadline_at <= now` | `TIMER-003` | | `FarmFulfillmentReminderJob` | 履约 `status in (pending_address,partially_shipped,shipped)` 且 `next_reminder_at <= now`;阶段读取 `address_due_at/receive_due_at` | `TIMER-004` | | `ProductMaterialExpiryJob` | 已批准 profile 的当前必需材料 `status=active`,按 `expire_at` 判断并按 `product_id` 去重 | `TIMER-005`、`MAT-001~004` | | `TraceMaterialExpiryJob` | 溯源材料 `status=active`,按 `expire_at` 判断 | `TIMER-005` | 其余 `31` 个 Timer/Job 同样从 `32` 自动生成选择器快照。所有选择器统一附加 `TIMER-006~008`:截止等值边界、错误状态排除、截止字段与 ID 游标、租约争抢及锁内重查。测试不得把字段名近似、同义状态或 `update_time` 当作合法替代。 ### 4. 四队列隔离 四条逻辑队列必须隔离: | 队列 | 任务性质 | 断言 | | --- | --- | --- | | `farm-critical` | 支付事实修复、用户/商户入账、退款、回购、异常执行 | 低并发严格锁,不被通知或报表积压拖慢 | | `farm-business` | 活动、供货、批次、分配、履约 | 有界并发、业务键租约和背压 | | `farm-notification` | 通知和提醒 | 渠道失败不回滚业务事实 | | `farm-maintenance` | 对账、缓存修复、附件清理和失败告警 | 可限速、可暂停,恢复后按原键追平 | ## 十二、环境、测试数据与支付规则 | 环境 | 用途 | 必须隔离 | 禁止事项 | | --- | --- | --- | --- | | `LOCAL/DEV` | UT、组件、注册表静态审计、单模块 DB 测试 | 开发者专用数据库/schema、Redis DB/前缀、文件目录 | 连接共享演示库执行清理或支付回调 | | `SIT` | 90 表集成、242 操作契约、104 事件、48 Job、四端 API/E2E | 专用数据库、四队列前缀、对象存储前缀、支付/物流/短信 Stub | 复用生产密钥、真实用户和真实商户数据 | | `MINIAPP` | 微信开发者工具和真机关键流程 | 测试 AppID/环境、测试用户、测试支付配置 | 用 H5 通过替代小程序验收 | | `PRE` | 性能、故障注入、DR、UAT 和发布候选 | 生产同构但数据隔离的数据库、Redis、队列、文件和监控 | 直接复制未脱敏生产数据 | | `PROD-SMOKE` | 发布后只读检查和受控小额闭环 | 专用合成账号、可追踪业务号 | 装载 Fixture、批量清理、故障注入或跑压力测试 | - 每个环境必须显式设置 `SMARTFARM_TEST_ENV`、数据库名、Redis DB/Key 前缀、队列前缀、文件前缀和 `run_id`;任一项缺失时清理器拒绝运行。 - 固定时钟只允许 LOCAL/DEV/SIT;PRE 的 Timer 演练使用受控时间窗口或专用测试记录,不修改系统时间。 - DEV/SIT 使用仅非生产可启用的受控支付适配器和固定签名回调 Fixture。 - 支持官方沙箱的支付渠道另跑沙箱,但沙箱通过不替代本地重复、乱序、超时和迟到回调测试。 - UAT 使用真实小额支付、退款和迟到退款闭环,金额、账号和证据由发布负责人单独控制。 - 测试报告只记录脱敏业务号和渠道结果摘要,不记录支付密钥或完整回执。 - 物流、短信、模板消息和地图使用受控 Stub 覆盖成功、超时、限流、非法响应和降级;另有少量真实联通性验收。 ## 十三、证据目录与格式 每次运行必须建立: ```text smartfarm_qa/artifacts// run-manifest.json registry-audit.json junit.xml coverage/ / attempt-001/ case.json request-response.json db-assertions.json event-job-assertions.json browser-trace.zip screenshots/ cleanup.json ``` `run-manifest.json` 必含: ```text run_id, environment, git_sha_by_project, database_schema_version, fixture_versions, registry_hashes, config_hash_redacted, tool_versions, browser_or_terminal, started_at, finished_at, executed, passed, failed, skipped, blocker_count, artifact_root ``` 单例证据要求: | 层级 | 最低证据 | | --- | --- | | `UT/COMP` | 测试名、输入、期望、实际、覆盖率片段 | | `DB/API` | 脱敏请求/响应、事务前后主事实、唯一键/锁/恒等式断言、清理结果 | | `EVT/JOB` | event/job/result key、Outbox、消费日志、重试次数、租约/游标、最终投影 | | `E2E` | 页面编号、浏览器/视口、Trace、关键截图、关联 API 和业务号 | | `PERF` | 负载脚本哈希、数据规模、吞吐、P95/P99、错误率、资源曲线和数量守恒结果 | | `UAT/DR` | 角色、步骤、签字人、时间、版本、恢复点、对账结果和未决项 | 证据中的 Token、密码、支付密钥、完整地址、手机号和第三方完整回执必须脱敏。无法复现到代码 SHA、数据库版本和 Fixture 版本的截图,不算有效通过证据。 ## 十四、P0/P1/P2 与覆盖门槛 ### 1. 优先级 | 优先级 | 定义 | 默认范围 | 发布处理 | | --- | --- | --- | --- | | `P0` | 错误会造成资金、库存、权益、越权、不可恢复状态或普通商城回归 | 注册表集合门、W3、关键 W2、支付退款、供货处置、结算回购、权限范围、动物导入、Timer 终态、自提处置、DR | `100%` 执行且通过,不允许跳过或豁免 | | `P1` | 主流程可绕行但影响履约效率、审核、证据、通知、地图或主要页面 | W1/W2 非资金路径、商户补证/物流、服务端作业、地图、页面状态、导出 | `100%` 执行,发布候选通过率不低于 `98%`;失败必须有负责人、影响分析和书面豁免 | | `P2` | 额外兼容、非关键性能梯度、视觉细节和增强体验 | 扩展浏览器/视口、长尾文案、非关键报表和额外压力梯度 | 目标通过率不低于 `95%`;不得掩盖 P0/P1 缺陷 | 单个 `case_id` 的优先级写入 `registry/domain-cases.json`;写操作元测试的优先级由风险级和维度共同决定。任何缺失注册、集合不相等、测试无法启动或证据缺失本身均按 P0 失败处理。 ### 2. 覆盖门槛 | 范围 | 门槛 | | --- | --- | | 90 张表 | `TABLE::` 全部通过列、类型、可空、默认值、唯一键、普通索引、逻辑引用和升级验证;集合覆盖 `100%` | | 242 个写操作 | 顶层元测试 `100%` 存在;所有适用维度 `100%` 通过 | | 104 个事件/114 条生产映射 | schema、生产提交/回滚、消费幂等、失败重试和重放映射覆盖 `100%` | | 48 个 Job | Job 登记覆盖 `100%`;40 个 Timer 的精确选择器、边界、游标、租约和锁内重查覆盖 `100%` | | 421 个领域用例 | P0 `100%` 通过;P1/P2 达到上表门槛 | | 后端新农业领域代码 | 行覆盖率不低于 `85%`、分支不低于 `80%`;金额、库存、数量恒等式和状态终结核心函数分支 `100%` | | 新增前端领域工具/组件 | 语句覆盖率不低于 `80%`、分支不低于 `70%`;关键页面另由 E2E 覆盖 | | 普通商城回归 | `REG-001~012` 全部通过,未绑定商品/订单不得新增农业事实或锁 | 覆盖率只是一道辅门,不能用高覆盖率替代金额算例、并发争锁、状态竞态和真实跨端流程。 ## 十五、自动审计与发布门 ### 1. 自动审计 每次测试基线变更必须比较: - `22` 的 case-like 集合为 `323`:`domain-cases.json` 精确接收 `316` 个测试用例,`gates.json` 精确接收 `G5-001~007` 七项决策。 - 本文第八、九节的 `89 + 16 = 105` 个 `case_id` 集合;与 `22` 不得重号。 - 三部分领域用例并集必须为 `421`,顶层测试登记项必须为 `663`。 - `31` 与写操作注册表的 `242` 个 `operation_code` 集合;特别断言三项 `CW_FULFILLMENT_*` 操作存在。 - `32` 与事件注册表的 `104` 个唯一事件、`114` 条生产映射集合。 - `32` 与 Job 注册表的 `48` 个唯一 Job、`40` 组 Timer/Job 集合。 - `17/30/35` 的 108 个页面集合。 - `15/34` 的 90 个表集合;必须包含 `eb_farm_cloud_supply_return`、`eb_farm_cloud_supply_acquisition`、`eb_farm_async_operation` 和 `eb_farm_admin_scope`。 - `19/31/37` 的写路由、操作码、DTO 和异步响应必须一一可追踪。 ### 2. 通过条件 - S0、S1 缺陷为 0。 - `242` 条写操作元测试和 `421` 条领域专用测试达到对应优先级门槛。 - 90 表、104 事件、114 生产映射、48 Job、40 Timer 和 108 页面集合审计全部通过。 - 平台自营供货、退回/承接实体与三段式执行、材料到期全量重算、范围重启用、动物导入和异步操作专项全部通过。 - `CW_FULFILLMENT_LOGISTICS_UPDATE`、`CW_FULFILLMENT_EVIDENCE_ADD`、`CW_FULFILLMENT_RETURN_RECEIVE` 的操作元测试及 `CW-MFUL-001~003` 全部通过;`CW-MFUL-004` 验证商户异常入口。 - `TIMER-001~008` 和 `PICKUP-REC-001~006` 全部通过。 - `ATTACH-001~002` 使用相同数值的双 ID 域 Fixture 通过,异步结果文件仍只接受系统附件域。 - 资金、库存、容量的并发、幂等和故障注入通过。 - 普通商城 `REG-001~012` 全部通过。 - 性能最低线通过,峰值更高时按预测峰值 `1.5` 倍复核。 - `DR-001~008` 在 PRE 或等价隔离环境演练通过。 - UAT 角色完成验收并关联版本化证据。 本文当前只定义测试目录、Fixture 和发布门,尚未创建测试工程或产生通过结论。 ## 十六、关联文档 - [12-v1-business-decisions-and-glossary.md](12-v1-business-decisions-and-glossary) - [19-v1-api-contract-draft.md](19-v1-api-contract-draft) - [22-v1-test-acceptance-release-manual-plan.md](22-v1-test-acceptance-release-manual-plan) - [31-v1-write-operation-contract-registry.md](31-v1-write-operation-contract-registry) - [32-v1-event-job-operation-registry.md](32-v1-event-job-operation-registry) - [33-v1-state-exception-transaction-matrix.md](33-v1-state-exception-transaction-matrix) - [34-v1-database-field-dictionary.md](34-v1-database-field-dictionary) - [37-v1-api-field-contract-registry.md](37-v1-api-field-contract-registry)