Banana Slides Release Gauntlet:面向生成式 AI 产品的 8 级发布前自动化验收方案

Banana Slides Release Gauntlet:面向生成式 AI 产品的 8 级发布前自动化验收方案

【免费下载链接】banana-slides 一站式原生AI PPT生成应用,几分钟内生成一套幻灯片; 支持上传任意模板图片,上传任意素材&智能解析,一句话/大纲/页面描述自动生成PPT,口头修改指定区域、一键导出可编辑ppt、视频等 - An AI-native slides generator based on nano banana pro🍌 【免费下载链接】banana-slides 项目地址: https://gitcode.com/gh_mirrors/ba/banana-slides

本文完整解读 Banana Slides 仓库中的《Release Gauntlet 发布前自动化测试验收方案》(docs/superpowers/specs/2026-07-02-release-gauntlet-test-plan.md),核心目标是用一条命令 npm run release:gauntlet 自动发现绝大多数功能与体验问题,并对无法自动验证的剩余风险生成明确的《残余风险报告》交给开发者做最小化人工抽查。读完本文,你将掌握"按判定器强弱分层配 Oracle""体验问题不变量化""VLM-as-Judge 质量评审""多人格 Agent 探索"等一套可直接落地的 AI 产品发布验收方法论,并看到它在 Banana Slides 现有 unit/e2e 资产上的具体挂载方式。

0. 第一性原理:为什么"99% 自动检出"不能靠堆测试用例

一个 bug 被自动发现,必须同时满足两个条件:

  1. 触达(Reachability):测试执行路径覆盖到了出问题的状态;
  2. 判定(Oracle):存在一个自动化的"对/错"判断标准。

传统测试方案(本项目现有的 unit + e2e)在两个维度上都有结构性盲区:

  • 触达盲区:测试只走"编写者想到的路径"。真实用户会乱点、中途刷新、断网、开两个标签页、上传奇怪的文件。
  • 判定盲区:Banana Slides 是生成式 AI 产品,核心产出(幻灯片图片)没有唯一正确答案。expect(x).toBe(y) 无法判断"这页 PPT 文字被截断了""对比度太低看不清"——而这些恰恰是用户最在意的"体验问题"。

所以本方案的核心不是"写更多用例",而是按判定器(Oracle)的强弱把产品分层,给每一层配上它能用的最强判定器:

产品层行为性质最强可用 Oracle
API 契约 / DB / 任务状态机 / 导出文件结构确定性精确断言、Schema 校验、属性测试
前端 UI 逻辑 / 路由 / i18n / 状态管理确定性e2e 断言 + 控制台零报错 + 视觉回归
用户旅程的健壮性(乱序操作、异常输入、网络故障)半确定性不变量断言(永不白屏、永不无提示等待、永不静默失败)+ Agent 探索
AI 生成产物质量(排版、可读性、贴合描述)概率性VLM-as-Judge(视觉模型按评分卡打分)
主观审美 / 品味主观无自动 Oracle → 进入残余风险报告

关键洞察:"体验问题"大多可以转写成不变量(invariant),从而变成可自动判定的:

  • 「困惑的说明文字」→ 不变量:所有可见文案必须在 i18n 字典中成对存在(zh/en),且 VLM 审阅每个界面截图回答"这个界面上有没有让新用户困惑的文案?"
  • 「无提示的等待」→ 不变量:任何 >800ms 的 pending 网络请求期间,页面上必须存在 loading 指示元素(spinner/skeleton/progress)。这条可以写成 Playwright 全局钩子,挂在全部 70 个现有 e2e 上白捡覆盖。
  • 「点了没反应」→ 不变量:任何 click 后 2s 内必须发生 DOM 变化、路由变化或网络请求之一。
  • 「白屏/崩溃」→ 不变量:任何时刻 console 无 uncaught error,root 元素非空。

这些不变量的提出并非空想,它们与仓库现状一一对应:例如 frontend/src/hooks/useT.ts 实现了"组件级内联字典 + 全局字典 fallback"的 i18n 机制,useT() 接收 { zh, en } 双层字典——这种组件级内联最容易漏翻,也正是 L0 的"i18n 完整性扫描"要覆盖的对象;而 e2e 中已大量出现对 loading 状态的显式等待(如 frontend/e2e/ui-full-flow.spec.ts 中对"生成中..."按钮与 skeleton 的轮询),说明"无提示等待"确实是真实痛点。

1. 总体架构:8 层流水线(Release Gauntlet)

按"便宜的先跑、贵的后跑、fail-fast"排列。L0–L3 是现有资产的加固,L4–L7 是新增的、真正拉开与普通项目差距的部分。

L0 静态防线(~2min)      → lint / tsc / py_compile / 依赖审计 / 迁移可逆性 / i18n 完整性
L1 单元+集成(~5min)     → 现有 pytest + vitest(补齐属性测试)
L2 契约防漂移(~3min)    → 后端 OpenAPI schema ⇄ 前端 mock ⇄ 真实响应 三方一致性
L3 确定性 E2E(~15min)   → 现有 70 个 spec + 全局不变量钩子 + 视觉回归矩阵
L4 产物验证(~10min)     → PPTX/PDF/视频/编辑版 PPTX 的结构级深度校验
L5 真实 AI 全流程(~25min)→ 现有 ui-full-flow + provider 矩阵 + VLM 质量评分
L6 Agent 探索测试(~40min)→ 多人格 AI agent 驱动真实浏览器做破坏性/探索性测试
L7 混沌与升级(~15min)   → 故障注入、并发、旧版本数据升级、环境矩阵
→ 产出《发布报告》+《残余风险报告》

总时长 ≈ 2 小时(L5–L7 可并行压到 ~1h)。按项目"不在意测试成本"的原则,真实 API 调用费用预计每次 $3–8。

这条流水线与仓库里现成的 CI 资产是叠加关系而非替换关系:.github/workflows/ 下已存在 ci-test.yml(PR 快检)、nightly.yml(夜间任务)、release-desktop.yml(桌面端发布)等工作流,方案在第 4 节明确了它们的挂法(见下文)。

2. 各层详细设计

L0 静态防线(新增 3 项)

现有:flake8(根目录 package.json 的 lint:backend 已配置 uv run flake8 backend/ --count --select=E9,F63,F7,F82)、eslint(lint:frontend 走 cd frontend && npm run lint)、npm run build。新增:

  1. tsc --noEmit 严格类型检查(build 能过不代表类型干净)。仓库前端已含 build:check(tsc && vite build)先例,说明项目认可"类型检查先于构建"的思路,L0 把它变成 release 前的硬门槛。
  2. 迁移可逆性测试:空库 alembic upgrade head → downgrade base → 再 upgrade head;再用上一个 release tag 的 DB fixture 直接 upgrade(见 L7)。仓库 migrations 目录下有 35 个版本文件(backend/migrations/versions),含多个 *_merge_* 与 make_settings_columns_nullable_for_env_* 这类涉及数据变动的迁移,可逆性验证的必要性显而易见。
  3. i18n 完整性扫描:脚本遍历所有 useT() 内联字典,断言 zh/en 键成对、无空串、无残留的 TODO/中英混杂。仓库全局字典位于 frontend/src/locales/en.json 与 frontend/src/locales/zh.json,而组件级内联字典散布在各组件中——这正是最容易漏翻的部分。

L1 单元 + 属性测试

现有测试保留。新增 property-based testing(后端 hypothesis)打确定性核心:

L2 契约防漂移(本项目最大的隐藏风险)

现有 70 个 e2e 里大量使用 page.route() mock。mock 与真实后端漂移是这类测试体系最经典的假阴性来源:后端改了字段名,mock e2e 全绿,真实环境全挂。

对策(三方一致性):

  1. 后端用 flask 路由自动导出 OpenAPI schema(apispec 或手写 schema 文件均可)。
  2. 写一个 pytest:对每个端点用 seed 数据发真实请求,响应体用 schema 校验。
  3. 写一个 lint 脚本:扫描 frontend/e2e/**/*.spec.ts 中所有 page.route() 的 mock JSON,用同一份 schema 校验。mock 不符合 schema = 测试自身失败。

从此 schema 是唯一事实源,前后端和测试三方谁漂移谁报警。这一层直接回应了仓库里大量 e2e 依赖 mock 的现状——例如 frontend/e2e/ui-full-flow-mocked.spec.ts 与 frontend/e2e/ui-full-flow.spec.ts 并存,前者不消耗真实 API 成本但依赖 mock 数据的真实性。

L3 确定性 E2E:全局不变量钩子(性价比最高的一项)

不新写用例,而是给 playwright.config.ts 加全局 fixture,让现有全部 spec 在跑原有断言的同时,免费检查 §0 列出的体验不变量:

- console error/warn 收集器:任何 uncaught error / React warning → 测试失败
- 网络监听器:任何非预期 4xx/5xx → 失败;>800ms pending 且无 loading 元素 → 失败
- 死按钮探测:每次 click 后 2s 无任何反馈 → 失败
- a11y 快扫(axe-core):严重级别违规 → 失败(对比度、无 label 的输入框
  本身就是"体验问题")

现有配置 frontend/playwright.config.ts 已经具备很好的挂载基础:testDir: './e2e'、testMatch: '**/*.spec.ts'、fullyParallel: true、失败时保留截图/视频/trace(screenshot: 'only-on-failure' 等),并且 webServer 会通过 docker compose up -d 拉起后端。方案要做的,是新增一个全局 fixture 注入不变量检查器,让约 70 个 spec(frontend/e2e/ 下现有 spec 文件数量与此吻合)零改动地获得新 Oracle。

视觉回归升级为矩阵:现有 frontend/e2e/visual-regression.spec.ts 已用 toHaveScreenshot + maxDiffPixels 做基线比对,方案将其扩展到 {zh, en} × {desktop 1280, mobile 375} × 关键页面(Home / Outline / Detail / Preview / Settings / History),基线截图入库,diff 超阈值即失败。移动端视口是现有测试完全没覆盖的盲区(当前 playwright.config.ts 的 projects 只配置了 chromium 桌面视口;memory 里也记录了要避免 hover-only 交互)。

L4 导出产物深度验证

导出是用户拿到手的最终交付物,一票否决。对 seed 项目(frontend/e2e/helpers/seed-project.ts 已支持免 AI 造数据:直接把 fixtures 图片落盘并直改 SQLite,绕过 AI 图片生成)执行全部导出路径,然后打开文件验内脏,而不只是断言 HTTP 200:

  • PPTX:python-pptx 打开 → 页数一致、每页含图、页面比例与项目设置一致、文件能被 LibreOffice headless 转 PDF 不报错(近似"能被 Office 打开"的自动化代理)。
  • 编辑版 PPTX:提取的文本框内容与页面描述文本做包含性比对;字体/位置字段非空。这依赖 backend/utils/pptx_builder.py 的编辑版导出实现。
  • PDF:pypdf 校验页数、页面尺寸、每页有内容流。
  • 视频:ffprobe 校验时长 >0、有视频流、(若配了旁白)有音频流、无损坏帧。视频导出逻辑在 backend/services/tts_video_service.py。

顺带一提,现有 ui-full-flow.spec.ts 已经在下载 PPTX 后用 validate_pptx.py 脚本做了初步内容校验(校验页数、关键词包含),L4 是把这种"下载成功即通过"升级为系统性结构校验。

L5 真实 AI 全流程 + VLM 质量评审(解决"生成质量"盲区)

在现有 nightly ui-full-flow.spec.ts(真实 Gemini)基础上:

  1. Provider 矩阵:gemini 真跑;openai/vertex 至少跑到"请求构造正确 + 能解析真实格式的录制响应"(用录制回放,避免多份 API key 成本)。仓库的 provider 抽象层(backend/services/ai_providers/ 下的 text/、image/、ocr/ 子目录)为这种矩阵提供了清晰的边界。

  2. VLM-as-Judge:全流程生成的每页幻灯片图片 + 对应页面描述,送给视觉模型(Gemini/Claude),按固定评分卡打分:

    逐项 0–2 分:文字完整无截断 / 无元素重叠 / 对比度可读 /
    内容与描述相符 / 版式基本对齐 / 无明显 AI 伪影(乱码字、畸变图标)
    任一项 0 分 → 该页 FAIL,附截图和理由进报告
    

    同一模型跑 3 次取多数投票压制评审随机性。这是把"人眼验收"自动化的核心组件。仓库中 backend/services/ai_providers/image/ 已有基于视觉模型能力的基础设施(如 subject_extraction_provider、rmbg_segmentation_provider),VLM 评审可复用同一套视觉模型接入通道。

  3. 界面文案审查:对 L3 矩阵产生的每张关键页截图,让 VLM 回答"假设你是第一次使用的用户,这个界面上是否有困惑、歧义或中英混杂的文案?"——直接对应项目既有 UX 约束中"避免困惑文案"的要求。

L6 Agent 探索测试(覆盖"没人想到的路径")

用 Claude Agent SDK(或 Claude Code headless + Playwright MCP)启动 5 个人格 agent,各自在独立 seed 环境里自由使用产品 30 分钟,唯一的判定标准就是 L3 那套全局不变量(白屏/报错/死按钮/无提示等待)+ agent 自身的主观报告:

人格行为脚本倾向
小白用户只看界面提示操作,遇到看不懂的文案就记录
急性子疯狂连点、不等 loading 就切页、生成中途刷新/后退
破坏者超长输入、emoji/RTL 文本、0 页大纲、上传 200MB 文件、非法文件改后缀
双开用户两个标签页同时编辑同一项目(SQLite 并发写的经典雷区)
英文移动端用户en locale + 375px 视口走完整流程

Agent 探索的本质是用 LLM 的常识替代人类测试员的直觉去扩大触达面。每个 agent 结束后输出结构化 findings(截图 + 复现步骤),由一个汇总 agent 去重、按严重度排序、并自动尝试用 Playwright 写出最小复现脚本——能稳定复现的进 bug 列表,不能复现的进残余风险报告标记为 flaky 疑点。

值得说明的是,"双开用户"人格针对的是一个真实风险点:仓库后端使用 SQLite(frontend/e2e/helpers/seed-project.ts 中直接对 backend/instance/database.db 执行 SQL),两个标签页并发写是 SQLite 的经典雷区,L7 的并发压测也会专门盯住 database is locked。

L7 混沌、并发与升级

  1. 故障注入(Playwright route + 后端故障开关):
    • AI API 返回 429/500/超时/截断 JSON → 断言前端有用户可读的错误提示且可重试;
    • 生成图片进行到 50% 时 kill 后端再拉起 → 任务状态可恢复或明确失败,不僵死 pending;
    • 磁盘写满(小容量 tmpfs 挂载 uploads/)→ 导出给出明确错误。
  2. 并发压测:10 个项目同时生成 → ThreadPoolExecutor(见 backend/services/task_manager.py)不死锁、SQLite 无 database is locked 泄漏到用户、任务全部到达终态。
  3. 升级测试:仓库里存一份上一 release 的真实 DB + uploads fixture,新版本直接启动其上 → 迁移成功、历史项目可打开、可继续编辑导出。每次 release 后由脚本自动刷新这份 fixture。这正是 L0"迁移可逆性测试"里"用上一个 release tag 的 DB fixture 直接 upgrade"的配套动作,仓库 35 个迁移版本的存在让这类测试有了实际价值。
  4. 环境矩阵:docker-compose(根目录 docker-compose.yml)、Dockerfile.allinone、源码直跑三种方式各做一次冒烟(启动 → 健康检查 → 创建项目 → seed 导出)。

3. 残余风险报告(那 1% 的诚实清单)

流水线最后一步自动生成 release-report/RISK.md,内容不是套话,而是由本次运行的实际覆盖数据推导:

  1. 本次未触达清单(自动统计):未真跑的 provider×model 组合、未覆盖的浏览器(只测了 Chromium;Safari/Firefox 未测)、未测的操作系统字体渲染差异。
  2. 无自动 Oracle 的项(固定 + VLM 标记的低置信项):
    • PPTX 在真实 PowerPoint / WPS / Keynote 中的渲染保真度(LibreOffice 转换只是代理指标);
    • 幻灯片的审美品味(VLM 只能判"错",不能判"美");
    • 视频旁白的语音自然度;
    • 上游 AI API 未来行为变化(今天全绿不代表下周模型更新后还绿)。
  3. 人工抽查清单(≤10 分钟):由以上两项生成的具体动作,例如"用 PowerPoint 打开 release-artifacts/sample.pptx 翻一遍""肉眼看 VLM 打了 1 分(及格线边缘)的这 3 页截图"。
  4. Flaky 隔离区:本次重试后才通过的用例列表——它们是未来 bug 的高发预测区。

这份报告把"自动化没覆盖到的地方"显式暴露出来,避免"测试全绿 = 可以放心发布"的错觉。

4. 与现有资产的关系 & 落地路线

阶段内容工作量检出增益
P1(先做,性价比最高)L3 全局不变量钩子 + console/网络/loading 监听挂到现有 70 个 spec;L0 三项新增;L4 产物深度校验~3 天高:现有用例覆盖面 × 新 Oracle
P2L2 契约三方一致性;L1 属性测试;L7 升级/并发测试~4 天高:消灭 mock 漂移假阴性
P3L5 VLM-as-Judge + provider 矩阵;视觉回归矩阵~3 天中高:生成质量首次可自动判定
P4L6 多人格 agent 探索 + 自动复现脚本生成;残余风险报告生成器~5 天中:覆盖长尾路径

入口统一为:

npm run release:gauntlet          # 全量,release 前必跑
npm run release:gauntlet -- --fast  # L0–L4,日常合并前

CI 挂法:现有 ci-test.yml 不动(PR 快检);nightly 跑 --fast;打 release tag 时跑全量并把两份报告附到 GitHub Release。这与仓库现有工作流划分一致:.github/workflows/ 下 ci-test.yml / pr-quick-check.yml 承担 PR 快检、nightly.yml 承担夜间验证、release-desktop.yml 承担桌面端发布构建,Release Gauntlet 作为发布前的最终关卡叠加其上。

5. 诚实的边界声明

  • "找出 99% 问题"作为渐近目标成立,作为承诺不成立——测试只能证明 bug 存在,不能证明不存在(Dijkstra)。本方案的可证伪指标是:发布后逃逸缺陷数。每个逃逸缺陷做归因(属于哪层的触达/判定失败),反哺对应层。这个闭环(而非任何一次性的用例集合)才是验收体系真正"无敌"的部分。
  • VLM 评审和 agent 探索是概率性组件,会有假阳性(误报)——用多数投票和自动复现脚本过滤;也会有假阴性——靠残余风险报告兜底。
  • 成本随层数上升:L5–L6 每次运行有真实 API 开销,已按项目"不在意测试成本"原则设计,但 --fast 模式保证日常开发零额外成本。

6. 方案精髓速览

  • Oracle 分层是总纲:确定性层用断言与 Schema,半确定性层用不变量,概率性层用 VLM 评分,主观层诚实降级为人工抽查清单——每一层都只使用它能承载的最强判定器。
  • 不变量是体验问题的可计算形式:白屏、无提示等待、死按钮、困惑文案,全部可写成 Playwright 全局钩子,且能挂在既有 spec 上白捡覆盖。
  • 契约三方一致性堵住 mock 假阴性,这是"测试全绿、上线全挂"类事故的根治方案。
  • 残余风险报告把不可自动验证的部分显式化,配合"逃逸缺陷归因反哺"的闭环,让发布验收体系随项目演进持续变强。

对想要在自己项目中复制这套方案的团队,建议从 P1 起步:先给现有 e2e 挂上全局不变量钩子(L3),再补静态防线与导出产物校验(L0/L4),用最小的成本获得最大的检出增益。

【免费下载链接】banana-slides 一站式原生AI PPT生成应用,几分钟内生成一套幻灯片; 支持上传任意模板图片,上传任意素材&智能解析,一句话/大纲/页面描述自动生成PPT,口头修改指定区域、一键导出可编辑ppt、视频等 - An AI-native slides generator based on nano banana pro🍌 【免费下载链接】banana-slides 项目地址: https://gitcode.com/gh_mirrors/ba/banana-slides

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值