Actual Budget Bug 修复 PR 浏览器验证手册:edge 复现 + 预览环境确认的闭环流程
【免费下载链接】actualA local-first personal finance app项目地址: https://gitcode.com/GitHub_Trending/ac/actual
导读
本文基于 Actual Budget 仓库中 review-actual-pr 技能 的配套测试手册,系统讲解如何对bug 修复类 Pull Request进行可验证的浏览器测试。核心方法是双环境证据闭环:先在线上构建edge.actualbudget.org上复现 bug,再在 PR 对应的 Netlify 预览环境中用同一套步骤确认修复生效,最终用真值表给出明确结论。读完本文,你将掌握从 PR 推导复现计划、使用playwright-cli驱动浏览器取证、处理预览环境失效与 demo 数据不足等边界情况,以及在代码审查报告中规范陈述测试结论的完整实战方案。
为什么 bug 修复 PR 需要"双份证据"
对于 bug 类 PR,测试阶段必须产出两类证据,缺一不可:
- 修复前 bug 确实存在:在
edge.actualbudget.org(线上 edge 构建)上按 PR 描述复现问题; - 修复后 bug 不再出现:在 PR 的 Netlify 预览构建上执行同样的复现步骤,确认行为已改变。
原手册对此给出了两个非常犀利的理由:
一个"看起来正确"但实际不改变运行时行为的修复,是潜在的回归隐患;一个在 edge 上根本复现不出来的 bug,说明修复可能是在解决一个"幽灵问题"。
也就是说,只看代码 diff 无法证明修复真实有效;只复现 bug 也无法证明修复已生效。两者互为印证,才能让测试结论具备证据力。
这一思路与仓库中 AGENTS.md 所倡导的"减少 mock、优先真实实现"的测试哲学一脉相承——浏览器测试尽可能在真实构建、真实数据上运行,而不是在理想化的测试桩里自说自话。
工作流总览与关键常量
整套流程分为四步:推导复现计划 → edge 复现 → 预览验证 → 结论判定。测试前先固定三个常量:
| 常量 | 值 | 说明 |
|---|---|---|
EDGE_URL | https://edge.actualbudget.org/ | 线上 edge 构建,代表当前主干代码的实际运行行为 |
PREVIEW_URL | https://deploy-preview-<num>.demo.actualbudget.org/ | PR 对应的 Netlify 预览,<num>替换为 PR 编号 |
| 输出目录 | ~/Downloads/pr-review-<num>/ | 一次评审的所有截图、元数据、diff 与报告集中存放 |
输出目录与 SKILL.md 中的工作目录约定一致:一次完整的 PR 评审会在这个目录下沉淀pr.json(gh pr view元数据)、diff.patch(gh pr diff)、review.md(评审报告)、before-edge.png与after-preview.png(bug PR 的成对证据截图),以及可选的findings.json结构化发现。
Step 1 — 从 PR 推导复现计划
测试的第一步不是打开浏览器,而是先回答一个问题:"这个 bug 到底怎么触发?"
从 PR 的标题、正文以及关联 issue 中,整理出一份有序、具体的操作步骤列表。原手册给出的示例值得借鉴:
打开 Reports → 点击 Cash Flow → 设置日期范围为上月 → 预期出现图表,实际观察到空白画布。
对比一下"具体"与"模糊"的差别:
- ❌ 模糊:"检查现金流水报表是否正常"
- ✅ 具体:"打开报表 → 点击现金流水 → 设置日期范围为上月 → 预期图表,观察空白画布"
步骤必须具体到可以在真实 UI 中逐步执行。如果 PR 正文提供的信息不足以推导出复现路径,则需要抓取关联 issue 的正文:
# 从 "Fixes #1234" / "Closes #1234" 中提取 issue 编号 ISSUE_NUM=... gh issue view $ISSUE_NUM --repo actualbudget/actual --json title,body,labels硬性红线:读完整理完关联 issue 后仍然无法得出清晰的复现步骤,必须停止测试阶段并告知用户,绝不凭空编造一个复现路径。这条"禁止伪造复现"的规则是整套技能的最高优先级约束之一,理由很简单——部分证据比没有证据更糟糕,一个编造的复现会让整个评审结论失真。
Step 2 — 在 edge 上复现 bug
确定复现计划后,先在线上 edge 构建上打开应用:
playwright-cli open $EDGE_URL playwright-cli snapshotplaywright-cli是本仓库评审流程依赖的浏览器自动化命令行工具:open打开指定 URL,snapshot输出当前 DOM 的可访问性快照(包含元素角色、名称与可点击性),后续所有点击都以快照中的引用(ref)为依据。
标准 demo 设置
首次进入应用会看到设置(onboarding)界面。按 AGENTS.md 中 "Testing and previewing the app" 一节的约定,执行标准 demo 初始化:
- 点击"Don't use a server"(不连接同步服务器);
- 点击"View demo"(加载演示预算)。
等待预算加载完成后,再逐步骤执行复现计划。
为什么选择 demo 预算而不是空预算?从源码看,createDemoBudget会以testMode: true的方式创建一个名为 "Demo Budget" 的测试预算(packages/loot-core/src/server/budgetfiles/app.ts),它预置了真实的账户、交易、分类和预算金额数据,远比空白预算适合验证报表、交易列表等需要数据支撑的功能路径。该 demo 预算的固定 ID 为_demo-budget,并且是多标签页 coordinator 中特殊对待的"可驱逐"预算组(参见 coordinator.ts 对create-demo-budget消息与_demo-budget组驱逐的处理),保证重复创建 demo 不会堆积残留状态。仓库 E2E 测试中同样依赖 demo 数据(如 onboarding.test.ts 加载ynab4-demo-budget.zip、actual-demo-budget.zip等演示数据文件),可见 demo 预置数据是项目测试基础设施的一等公民。
逐步骤取证
复现计划要一步一快照地推进:每执行一步点击后重新snapshot,确保下一步点击使用的是新鲜的 DOM 引用(页面状态变化后旧 ref 会失效)。当走到失败状态时,立即截图存证:
playwright-cli screenshot --filename=$HOME/Downloads/pr-review-<num>/before-edge.png在运行摘要中如实记录:bug 是否按描述复现了?
- 复现成功:继续 Step 3。
- 未复现:这是一个重要发现,必须在报告中如实说明并停止。可能的原因是该修复属于防御性改动,针对的是一条难以触达的路径——这种情况下应把观察到的现象升级给用户判断,而不是硬凑结论。
- demo 数据不足以支撑复现(例如 bug 需要多币种环境而 demo 是单币种的):同样明确说明并停止,绝不伪造。
Step 3 — 在预览环境验证修复
关闭 edge 页面,切换到 PR 的 Netlify 预览:
playwright-cli close playwright-cli open $PREVIEW_URL playwright-cli snapshot预览环境未就绪的处理
如果页面返回 404 或 "site not found",等待约 10 秒后重载一次即可——Netlify 部署有时会滞后于 GitHub PR 事件。若重试后仍然打不开:
- 停止测试;
- 在报告中说明预览 URL 无法加载;
- 代码审查照常交付(只是不含测试章节)。
绝不降级去测试一个过期构建——那会让"修复是否生效"的证据完全失效。
重复验证流程
预览加载成功后,重复同样的标准 demo 设置与同样的复现步骤(注意两个环境的 demo 数据是一致的,因此复现结果可以直接对比,这一点在 SKILL.md 的标准 demo 设置一节有明确说明),然后截图:
playwright-cli screenshot --filename=$HOME/Downloads/pr-review-<num>/after-preview.png此时你手上就有了成对的证据:before-edge.png(修复前 bug 存在)与after-preview.png(修复后 bug 消失)。
Step 4 — 判定结论:四象限真值表
在报告(SKILL.md 中定义了完整的报告结构,含 Testing 章节)中,用三行直白的陈述收尾:
Bug reproduces on edge: yes / noBug reproduces on preview: yes / noVerdict: fix confirmed | fix not observable | repro inconclusive
判定逻辑由真值表决定:
| Edge | Preview | 结论 |
|---|---|---|
| yes | no | fix confirmed(修复已确认) |
| yes | yes | fix not observable(修复不可观察)—— 升级处理 |
| no | no | repro inconclusive(复现无定论)—— 说明原因 |
| no | yes | regression(回归)—— PR 把问题改得更糟了 |
对每种结局的理解:
- yes → no(修复确认):最理想的结果,edge 上出 bug、预览上不出,双份证据齐备,修复真实改变了运行时行为。
- yes → yes(修复不可观察):bug 在两个环境都复现,说明修复在真实运行时并未生效——即使代码看起来"改对了",也要升级处理,这正是"看起来正确但没改变运行时行为"的那类风险。
- no → no(复现无定论):两个环境都复现不出,必须说明为什么(demo 数据不够?需要特定前置条件?),不能含糊带过。
- no → yes(回归):罕见但极其重要。edge 上没问题的行为在预览上反而出问题,说明 PR 引入了回归。一旦触发此情况,必须在代码审查章节同步标记为 Critical。
"回归"象限的存在正是双环境对比的价值所在:单环境测试永远无法发现"修复方案把原本正常的行为改坏了"这类问题。
测试实践的三个关键注意事项
1. 视觉类 bug 必须统一视口
如果 bug 属于视觉问题(布局、颜色、对齐),两个 URL 都要用相同的视口尺寸:
playwright-cli resize 1280 800在每次 demo 设置前执行。否则两个环境默认视口尺寸不一致,可能掩盖或伪造出差异,导致误判。feature PR 手册(browser-testing-feature.md)同样强调设置一个可呈现的视口(如 1440×900),可见视口一致性是浏览器测试取证的基础纪律。
2. demo 数据可能不够用,要如实说明
交易列表、报表类 bug 常常依赖足够规模的数据才能暴露。demo 预置数据规模有限,如果怀疑"数据量不够所以没复现",要明确说出来——不要用"看起来没问题"这种话搪塞,因为那意味着你实际上并未真正走通代码路径。这类"数据不足导致复现不充分"的情况,对应真值表中的repro inconclusive,必须说明原因。
3. 流程边界:何时该停,何时该继续
整个手册贯穿一条决策主线——何时必须停止:
| 场景 | 动作 |
|---|---|
| 无法从 PR 和 issue 推导出复现计划 | 停止测试,告知用户 |
| bug 在 edge 上未复现(可能为防御性修复) | 报告现象,停止并升级 |
| demo 数据不支持复现所需环境 | 说明并停止,不伪造 |
| 预览 URL 重试后仍不可用 | 停止测试,报告 URL 问题,代码审查照常交付 |
| 视觉类 bug 未统一视口 | 重新设置视口后再测 |
"停止并升级"不是消极逃避,而是对证据质量的负责——这条规则与 SKILL.md 的硬性规定(绝不伪造复现、绝不向 GitHub 回写任何评论)共同构成整套评审技能的可信度基石。
与仓库测试基础设施的衔接
这套浏览器验证流程并非孤立存在,它与仓库既有的测试体系深度衔接:
- E2E 测试:仓库在
packages/desktop-client/e2e/下用 Playwright 编写了覆盖账户、预算、报表、规则、日程等功能的端到端测试(本地运行方式见 AGENTS.md:yarn workspace @actual-app/web e2e),其中的页面模型(如 configuration-page.ts 通过 "Try the demo" 按钮创建 demo 文件)与手册中的 demo 设置流程一一对应; - 视觉回归测试(VRT):
yarn vrt/yarn vrt:docker负责快照级的 UI 回归比对,快照存放在各测试文件的*-snapshots/目录下,可作为视觉类 bug 的补充证据手段; - feature PR 流程:本文面向 bug PR;对于功能/增强型 PR,走的是另一套只测预览、带红色虚线高亮标注截图的流程(参见 browser-testing-feature.md 与标注脚本 highlight-element.js),两套手册共同覆盖了 PR 评审的浏览器测试环节。
总结
Actual Budget 的 bug 修复 PR 浏览器验证流程,本质上是一套以双环境对比为核心的证据闭环:
- 从 PR/issue 推导出可执行的复现计划(不可伪造);
- 在 edge 上确认 bug 真实存在(before-edge.png);
- 在 Netlify 预览上确认修复生效(after-preview.png);
- 用四象限真值表给出明确结论,并对
regression象限保持最高警惕。
这套流程的可贵之处在于它把"测试"从模糊的"看看行不行"变成了可复现、可取证、可判定的人工验收协议,并且为每一类失败场景都预设了明确的停止条件——既保证了评审质量,也保护了证据的真实性。对于任何需要验证"修复是否真的修好了"的 PR 评审场景,这套方法都值得直接复用。
【免费下载链接】actualA local-first personal finance app项目地址: https://gitcode.com/GitHub_Trending/ac/actual
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考