跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

测试

测试规划、e2e 场景清单与测试约定——质量保障的覆盖地图与走查底稿。

1 - QMTV 测试规划(Go 版,P0 底册)

回答移植需求②"基于现有项目先写单元测试——移植现有测试(如果有),或另写"。现状实测:冻结版零单测,仅 4 个 API 冒烟脚本(verify_*.js)覆盖 60/239 端点。结论:以 TDD 另写为主(pms 范式),verify 断言移植为集成冒烟底册,e2e 骨架按 pms 约定立。

1. 分层测试范式(对齐 pms backend)

层手段纪律
repo 层sqlmock(DATA-DOG/go-sqlmock);newMockDB 4 行 helper 就地定义,无共享 testutil断言 SQL 形状 + ExpectationsWereMet;结尾必校验
service 层手写 fake repo(map 内存副本);关键纪律=fake 忠实 gorp 语义(Insert 后 version=原值+1 等回写行为必须模拟,防掩盖差一缺陷)纯函数尽量抽出独立测(计费/解析器/提示词组装)
handler 层不测(薄层,零业务逻辑——域包四文件铁律保证)装配冒烟在 main_test.go
守卫cmd/server 三件(not_null/pointer_field/status_table),schema 六原则机器守卫负样本演练留档 TECH.md §9
集成冒烟//go:build integration 标签真库用例(对齐 pms test/smoke_test.go;MySQL 不可用自动 skip)+ verify 移植断言dev-up 环境跑
全局go test ./... -race -count=1 纯 mock 不连外部服务CI 缺省档卡点

2. 分域单测规划(先红后绿,TDD 顺序=P 期次)

域期必测纯函数/场景(首批)
authP1scrypt 往返(已有)、JWT 双格式(已有)、refresh 轮换状态机(签发→轮换→旧 token 拒→过期拒→改密全撤销)、注册送积分+邀请返佣、限流窗口边界 —— P1 已落地(service 11 场景 + repo sqlmock 7 + jwtsecret 3 + main_test 装配 4 + integration 全链/C8 互操作;限流 4 场景见 gateway 包)
creditsP1CAS 扣款成功/余额不足 402/版本冲突重试/退款 refunded 防重/balance_after 台账一致性/COSTS×settings 双层计费价 —— P1 已落地(billing 6 + repo sqlmock 6 + service fake 6 + integration 并发不超扣/台账对账/零台账);差异收口(PRD v1.3):CAS 谓词仅 credits>=? 下无版本冲突路径,RunWithRetry 定稿不引入;退款防重=credits.Refund 唯一口(F9),P2 W7 落地
taskP2Mock 规则拆解(场次切分/人名提取/景别轮转——preprocess.js 逐规则移植对拍)、parser.parseSplit 宽容解析(60 镜上限/img 1200 字)、LLM 拆解失败回退链 —— P2 执行中(2026-10-18 立项)
generationP2ratio→尺寸映射、videoCost(secs)、providers 三响应形态分发、轮询状态词判定、Mock SVG/WAV 字节头 —— P2 执行中
exportP2导出积分×段数、export_tasks 全链(期次随 TECH 域包表 P2,v1.3 对齐)
director/fusion/workbenchP3双表通路 _tbl 路由(Go videoSmart 显式表参数,P2 期初定型)、队列 recoverQueue、审片双入口
billing-adminP4充值到账+两级返佣、提现 7 态状态机、白名单键过滤(credit-settings PUT)

3. verify_*.js 断言移植矩阵(约 60 端点 → Go 集成冒烟)

现有脚本逐断言移植为 Go 集成测试(integration 标签,dev-up 环境执行;脚本本身保留在冻结区不动)。「可测期次」= 该端点 Go 实现落地期。端点数为约数(唯一路径口径):分项 ~28+~20+~6+~9 含同端点多场景重复计数,去重后约 60。

源脚本断言场景端点数可测期次Go 冒烟形态
verify_v14.js火花 join/me/阶梯;工作台三工具+列表;经典审片+回读;导演项目→分镜→导演审片+资产队列挂起;组织申请→审批→邀请→加入→非 owner 改角色拒→项目共享→成员可见~28P3(组织面 P4)Go httptest 或真库 curl 链
verify_v17.js企业看板/trend/双排行;writers 排序+主页;showcase 发布/撤下;全站搜索;剧本库新字段;素材夹+10GB 容量+assign;非 owner 建组拒;错密码改邮箱拒~20P4同上
verify_eval.jsevaluations/config;txt 上传;GBK 非法字节回退不崩;深度评估 stage 推进轮询;报告下载含逐集证据~6P3同上(stage 推进用 pollUntil)
verify_lib.jsgenres 配置;种子幂等回填;五维筛选;详情目录;rating/new 排序;管理端 CRUD+用户端 404~9P3同上
新增(脚本空白,各期验收补)登录/refresh 真轮换/改密;扣款 402/退款防重;拆解 v2 双引擎+回退;视频 v2 按秒计费;SSE 五类事件(Go 侧 client 断言帧格式);4 个 ZIP 端点结构;充值→审核→返佣→提现全链;模型接入 18 端点~179随 P1~P4每期验收新增集成用例

4. E2E 约定骨架(正式版 P5,按 pms docs/test 三文档体系)

  • 初始世界:独立库 qmtv_e2e(dev-up 变体建库导 full+seed);账号矩阵=seed 三账号+按需 API 注册;业务单据不进种子,一律 API 造数(防绕过状态机)。
  • 外部 API 零真实调用(用户指令 2026-10-17,instructions.txt):e2e/集成测试局限在本系统内,外部 API 调用会引起费用——全部 mock。LLM/图像/视频供应商一律走 Mock 通道(测试环境不配 model_endpoints 的 api_key,或显式 provider_routing=mock);网络出口断言(providers 适配层的真实 HTTP 调用)用 httptest 本地假服务器验证协议形状,绝不打真实供应商;CI 环境保持零 Key(llm.isAvailable()==false 全站 Mock 路径),真实供应商连通性只允许人工在管理后台用「测试连接」单次验证。
  • 确定性:时间用相对量;金额固定值;禁按自增 id 断言(qmtv 全字符串 ID 天然满足)。
  • 隔离:e2e-reset(DROP/CREATE+导入)/e2e-seed(快恢复);失败不自愈必须 reset;连跑两轮间隔 reset。
  • 明令禁止:禁 sleep 等事件链(一律 pollUntil,超时 20s——评估 stage 推进/视频轮询场景);禁 retry;5xx 直接抛响应体。
  • 场景登记:docs/test/e2e-qmtv-场景清单.md 行格式对齐 pms(场景ID E2E-XXX-NN|FSD 功能 ID|主干路径|关键断言|现状);缺陷修复覆盖优先并入现有场景加断言。
  • Playwright 引入与否:P5 决策——前端冻结的前提下,API-first 断言册已覆盖回归需求;截图册(操作手册配图)可单独用 Playwright 走真 UI,不与断言册共用一行代码。(二十六期已落地:前端演进后 Playwright 双配置入位——断言册 11 用例〔auth 4/dashboard/generation 2/credits/admin/nav/spark;含 setup 册 14〕 + 截图管线,约定见 docs/test/e2e-测试约定.md;本条 P5「前端冻结」前提已随 TS 演进裁决失效,双配置即终态。二十七期勘误:二十五/二十六期宣称「13 用例」系计数漂移,11 为亲数权威口径。)

5. CI 闸门(scripts/ci.sh,已落地)

档内容时长
–fastbuild+vet+check_consistency+冻结契约守卫(frozen_contract_check)+守卫三件<1min
缺省+全量 go test -race -count=1~2min
–with-env+dev-up+healthz+登录真断言+refresh 轮换断言(新旧 RT 不同/旧复刷 401)+query token 兜底+1min
–e2e=–with-env 全部 + e2e 环境(qmtv_e2e/:3301/frontend/dist 托管)+ Playwright 断言册——显式 opt-in,浏览器二进制不进日常闸门(二十六期第四档)+2min

JUnit 双断言(场景总数≠期望也阻断)随 P5 e2e 落地引入。

2 - QMTV E2E 测试约定

二十六期(2026-10-19)立册。对齐 pms e2e 约定骨架,按 QMTV 单库场景裁剪。 场景覆盖地图见 e2e-qmtv-场景清单.md。

§1 初始世界

  • 环境:bash scripts/dev/e2e/e2e-up.sh 一键起——独立库 qmtv_e2e(DROP/CREATE 即全量 reset)+ 端口 :3301(与 dev :3300 三隔离:库/端口/产物文件名,可共存)+ 托管 frontend/dist(每次 up 强制重建,永测当前 src)。停环境 e2e-down.sh;快恢复(不重建库)e2e-seed.sh。
  • 种子自检:e2e-verify.sh 六项(healthz / admin·demo·producer 三账号登录 / models-active / style-presets)——绿才能跑用例。
  • 账号矩阵:admin@qmtv.com(管理员,credits 100000)/ demo@qmtv.com / producer@xingmang.cn——密码=seed 公开演示值,不入新密。API 造数的辅助账号一律 e2e- 前缀 email;storageState 册(.auth/{admin,demo}.json)由 setup 项目真实 UI 登录一次产出,用例零登录(对抗 login 20/min 限流)。
  • 确定性规则:未配置 model_endpoints → 生成类全走内置 Mock 同步 done(无轮询等待、无外部超时);Mock 图像/视频字节含随机源——只断结构确定(卡片存在/URL 可达/台账行),绝不断素材内容。
  • 预置种子:SQL seed(admin/demo+分销配置+计费 KV)+ Go seed(producer+示例任务链)。业务单据不进种子,一律 API 造数。
  • 隔离与清理:用例各自造数各自收尾(集成侧 integCleanup 同纪律);失败不自愈——重跑前 e2e-up;连跑两轮必须间隔 reset(credits 水位会漂移)。

明令禁止

  1. 禁 sleep 等待 UI 条件——唯一合法等待面是 Playwright 自动等待/expect.poll/waitForEvent/pollUntil。豁免两处(登记):①巡检类用例的路由间静置窗口(nav/admin 的 waitForTimeout(400/1500)、snapshots 截图前 waitForTimeout(800)——错误收集窗/渲染落定窗,非断言等待);②截图前 networkidle。
  2. 禁 retry——config retries: 0(pms flaky 规则:禁 retry 掩盖;修复优先序 改等待>改定位>改断言>最后才是 retry)。
  3. 禁断全局计数/绝对余额——流水断言用 total 相对面 + 最新行身份;余额用 assertBal 恒等式(后端集成侧)。
  4. 禁触 qmtv_main / pms_ / sw_main*——e2e 只操作 qmtv_e2e 单库(远程 139 共享实例纪律平移)。
  5. SSE 面禁 networkidle——EventSource 长连接使 networkidle 永不触发;巡检用 load+双 rAF+静置窗口。

§2 可测性硬规则

  • 断业务结果,不断文案细节:toast 只断关键短语(「拆解完成」「去字幕完成」);选择器优先 role/placeholder/既有稳定 class,不批量加 testid(触碰面爆炸);高频锚点按需单点补并在此登记。
  • 失败留证:trace retain-on-failure + screenshot only-on-failure → e2e/.artifacts/(gitignore)。
  • 断言/截图分文件一行不共用(pms 硬规则):断言册 playwright.e2e.config.ts(testDir e2e,smoke 项目收 assertion/*.spec.ts);截图册 playwright.config.ts(只收 snapshots.spec.ts)。
  • API 侧错误信封直接抛(e2e/lib/client.ts apiReq):非 2xx 抛响应体——静默吞错=测试说谎。
  • 对话框断言用 waitForEvent('dialog')(once+变体捕获有竞态——auth.spec 负样本抓获);LoginView 错误走原生 alert,业务 confirm 各页分散(WorkbenchView 仅 repaint 空描述分支)——用例写前先读该页 submit 源码,勿凭笔记推 dialogs。

§3 运行手册

bash scripts/dev/e2e/e2e-up.sh          # 起环境+种子自检(首次/失败后/连跑第二轮前必跑)
cd frontend
npm run test:e2e                        # 断言册(smoke,:3301)
npm run test:e2e:headed                 # 有头观察
npm run test:snapshots                  # 截图管线(二十七期手册出图)
npx playwright show-trace <trace.zip>   # 失败取证
bash scripts/dev/e2e/e2e-down.sh        # 停环境
bash scripts/ci.sh --e2e                # 全栈验收档(=--with-env 全部 + e2e 册)

§4 flaky 处理规则

  • 72h 内同一用例红 ≥2 次 → 摘出开单,不得带红合入;
  • 7 天未修 → 删用例(场景清单「自动化?」列同步回落「待实现」);
  • 关键用例落地必配负样本演练(涉及金额/回归锁/A1 教训面——改断言键名/路径必红才转正;A1 fixture 死键教训:键名错→锚死力失效)。巡检类(nav/admin 只读遍历)可豁免——harness 判死力由其它用例的有机红佐证(二十六期如实报告:admin.spec 无单独负样本,nav/auth/credits/dashboard/generation 五处有机红已证)。

§5 场景登记与回归锁

  • 场景 ID 唯一(E2E-<模块>-<序号>),ID 标注于 spec 文件头注释(用例名可不带前缀)——清单与 spec 双侧 grep 对账按场景 ID 级(「自动化?=是」的行必须有对应 ID 的 spec 文件,清单「现状」列登记 ✅ 文件名)。〔二十七期勘误:原「用例同名对账」与实际不符——ID 在头注释非用例名,对账实为场景 ID 级 9=9+文件级 ✅ 列。〕
  • 缺陷修复优先「并入现有场景加断言」(回归锁),不新开用例——本仓 /review-plan A 类「验收锚点」判死力机制直接挂此。
  • 写链场景(导出 ZIP、充值审核、分销提现等)先登清单「待实现」行,后续期次升格。

3 - QMTV E2E 场景清单(覆盖地图)

行格式:场景 ID 唯一;「自动化?=是」行与 frontend/e2e/assertion/*.spec.ts 按场景 ID 级对账(清单 ID ↔ spec 文件头注释 ID+「现状」列 ✅ 文件名,与测试约定 §5 同口径;二十七期勘误:原「用例同名」与实情不符——用例 ID 在文件头注释非用例名)。 「FSD 功能 ID」列=场景↔功能规格双向对账锚(三十一期回填)——指向 prd/fsd-qmtv/ 各册 F<m>.<nn> 节;横切场景(积分/导航/截图)无单册归属标「横切」。 二十六期首批冒烟 8 场景全走 Mock 同步面(避开 SSE 依赖与长轮询);写链场景登「待实现」后续升格。

场景ID场景名模块/页面前置种子主干路径(系统视角)关键断言冒烟?自动化?FSD 功能 ID现状
E2E-AUTH-01登录/守卫/登出auth/LoginView+App 导航+router guard三账号 seed错密码 alert→admin 登录跳首页→未登录访 /dashboard 重定向→demo 无管理后台入口且直访 /admin 顶回→admin 可达 /admin 并登出回 /loginalert 文案「邮箱或密码错误」;URL 断言×4;权限分层入口可见性是是F1.01~F1.09(登录 F1.02)✅ auth.spec.ts
E2E-DASH-01工作台拆解提交dashboard/DashboardViewadmin 零任务POST /tasks/v2(Mock 同步)→toast→列表 invalidatetoast「拆解完成」;任务卡镜数>0(A1 回归锁:wire=驼峰 shotCount,误读蛇形恒 0 必红)是是F2.03(V2 拆解)+F2.01(列表)✅ dashboard.spec.ts
E2E-GEN-01独立图片生成independent-tools 图片 tabadmin 登录POST /images/generate(Mock 同步 done).img-card 即现且含提交提示词是是F3.08(图片素材)✅ generation.spec.ts
E2E-GEN-02工作台工具提交workbench/WorkbenchViewAPI 造 standalone video(standalone:true 必传)选工具→选成片→提交→Mock 同步 donetoast「去字幕完成」(去字幕无 confirm——confirm 仅 repaint 空描述分支)是是F11.01+F11.02(提交+轮询)✅ generation.spec.ts
E2E-CRD-01积分流水闭环credits/CreditsViewadmin 登录API 造图片生成→台账入账total 相对 +1;最新行含「独立图片生成(-10)」(不断首页行数——分页满页恒等碎)是是横切(总则 §2.3;台账 F1.06)✅ credits.spec.ts
E2E-ADM-01管理端只读巡检admin/AdminViewseed 三账号概览/用户管理/任务审计/剧本管理四 tab 遍历.stat≥5;用户行≥3;tab 面板渲染;零 5xx 零错误 toast是是F12.01+F12.02(跨 m01/m02/m09 tab 注记)✅ admin.spec.ts
E2E-NAV-01全站只读巡检20 路由全页遍历admin storageState逐页 goto+load+双 rAF+静置窗零未捕获 console error / 零 /api 5xx / 零 /api 网络失败(已抓获 spark 缺口)是是横切(全站路由)✅ nav.spec.ts
E2E-SPK-01火花计划加入链spark/SparkViewadmin 未加入(e2e-up 后初态)UI join→me invalidate「已加入」标签现;API me.joined=true;重跑容错(残留轮直断投影面)是是F13.01✅ spark.spec.ts
E2E-SNAP-01截图管线自检snapshots.spec.tsadmin storageState全站 24 图(公开 3+登录态 21;dashboard 填样例文本不提交;/export/:taskId 参数页豁免截列表态)落 docs/manual/images/PNG 字节非空+零重复字节(26 期四图→27 期 24 图扩容;settle 信号驱动 waitForFunction,公开页固定短 settle)是是横切(截图管线)✅ snapshots.spec.ts
E2E-SUB-01投稿→过审→剧本超市上架studio+admin 投稿审核demo 投稿+admin 审POST submissions→admin approve→library 可见状态机翻转+跨用户可见是待实现F9.03+F9.07(投稿+审核上架)二十七期候选
E2E-RCH-01充值凭证→审核入账recharge 双端demo 充值申请+admin 审POST recharge→upload 凭证→approve→余额+台账金额入账恒等式是待实现F8.01~F8.03二十七期候选
E2E-EXP-01成片导出 ZIP 下载export/ExportView已有 done 分镜GET-or-POST 导出编排→2s 轮询→ZIP 下载ZIP 魔数+分镜数是待实现F4.01(导出编排)后续候选
E2E-WD-01分销提现申请与审核distribution分销关系+佣金余额提现申请→admin 审→余额划转双向台账恒等式是待实现F7.03+F7.06(申请+审核)后续候选
E2E-DIR-01导演工作台分集拆解director3dadmin 登录建项目→拆分集→分镜图生成director_shots 回填是待实现F10.01~F10.06(项目/分集/分镜图)后续候选