生活分享

修复 Bug 的完整流程

好的除错从可重现的症状开始,再用证据缩小原因,最后验证修正。『网站坏了』不够具体;提供哪个输入、在哪个步骤、期待什么、实际出现什么,能让 Codex 更快找到相关程式。

阅读时间约 14 分钟 · 操作 25 分钟

实作顺序示意图,非产品介面截图。
图片:Mokaair (© Mokaair)
回总目录:Codex 学习中心:完整教程目录

实践 · Desktop / CLI / VS Code / JetBrains / cloud

本篇目录
  1. 目标与准备
  2. 步骤 1:固定故障版本与重现步骤
  3. 步骤 2:建立不依赖画面的最小重现
  4. 步骤 3:要求最小修正与原因说明
  5. 步骤 4:用同一证据做回归
  6. 排错习惯、还原与交付

目标与准备

本段提到的教学与资源:

步骤 1:固定故障版本与重现步骤

从练习 ZIP 的 broken 复制五个档案到新资料夹 codex-bug-lab,保留原版。这份程式已有筛选分支,但 Completed 的条件故意写反;与 start「尚未实作筛选」不同。开编辑器,PowerShell 用 Get-Location、macOS/Linux 用 pwd 确认位置,再执行既有测试,预期 2 过 1 败。

终端机:基准测试 · sh
node --test core.test.mjs

要确认画面,从本目录启动本机预览:Windows 执行 py -m http.server 4173 --bind 127.0.0.1,macOS/Linux 执行 python3 -m http.server 4173 --bind 127.0.0.1。开 http://127.0.0.1:4173;若有想保留的虚构资料先记录,再使用 Reset practice data,切到 All tasks 并确认空清单。接著依序新增 Read、Build,只勾选 Read,再切 Completed。预期应是 Read,故障版实际却显示 Build;把这个顺序完整记下。资料重设不会还原程式档。

故障报告要带执行环境、起点、操作、预期、实际与证据,先不要填「原因一定是快取」。下列范本只记已观察的现象;日期与测试结果由你填入。若你的画面显示不同,先核对预览目录及是否混入 expected,不把文章预期硬写成自己的实测。

文件范本:Bug 报告 · markdown
# Bug: Completed shows unfinished tasks
Environment/date: fill from this run
Fixture: broken copied to codex-bug-lab
Steps: reset practice data; add Read and Build; complete Read; select Completed.
Expected: Read only.
Observed: Build only, if reproduced.
Baseline: node --test core.test.mjs; fill actual result.
Scope: keep UI, storage format, ordering and tests unchanged.
Root cause: not confirmed yet.
Unperformed checks: list explicitly.

步骤 2:建立不依赖画面的最小重现

在根目录新增 repro.mjs,贴入下面完整程式。它直接把一个已完成与一个未完成任务送给 visibleTasks,不经 localStorage、DOM、浏览器快取或外部网路。保存后在另一个终端机执行 node repro.mjs。故障版应先印出实际 b,再因期待 a 而以非零状态结束;这次 assertion 失败就是要保留的证据。

新增档案:repro.mjs · javascript
import assert from "node:assert/strict";
import { visibleTasks } from "./core.mjs";

const tasks = [
  { id: "a", title: "Read", completed: true },
  { id: "b", title: "Build", completed: false },
];
const actual = visibleTasks(tasks, "completed").map((task) => task.id);
console.log("Completed IDs:", JSON.stringify(actual));
assert.deepEqual(actual, ["a"]);
console.log("Reproduction passed.");
终端机:最小重现 · sh
node repro.mjs

现在可以缩小调查:核心函式在没有浏览器的情况下就已回传错误,故障不需要快取或按钮事件才能发生。这不能证明所有 UI 都正确,但足以先查核心 Completed 分支。请 Codex 用证据解释「为什么目前条件选中了未完成任务」,再谈修正;不要以一次重新整理偶然正常当根因已找到。

先分辨程式失败与环境失败

若 node repro.mjs 显示 ERR_MODULE_NOT_FOUND,尚未执行到 Completed 断言,先检查目前资料夹与 core.mjs 的档名;若是 SyntaxError,核对是否完整贴上程式。只有程式成功载入,印出 b,接著因期待 a 而失败,才是此缺陷的重现。反过来,第一轮直接通过也不是你已修好:可能拿到 expected 副本,应回查材料来源。把命令、退出码、实际输出及副本位置一起留下,不只记「红色」或「失败」。

步骤 3:要求最小修正与原因说明

桌面版先以 codex-bug-lab 建立 Codex 任务;CLI 则在该资料夹确认路径后执行 codex。接著送出下面的完整要求,将范围限定到 core.mjs 的 Completed 条件。既有测试与 repro.mjs 都不要修改,否则无法比较前后。教材的故障注解在修好后会过期,可一并移除那一行;除此以外不重构所有函式、不改 UI 文案、不换框架。若代理没有读测试输出,就要求先确认原始失败再继续。

Codex 提示词:限定修正范围 · text
Fix the reproduced Completed-filter bug in this codex-bug-lab.
First read core.mjs, core.test.mjs and repro.mjs. Run node repro.mjs and node --test core.test.mjs to confirm the current failure.
Explain the predicate error using the actual a/b IDs. Modify only the completed predicate in core.mjs and remove its obsolete deliberate-bug comment. Do not change tests, repro.mjs, active behavior, storage or UI.
Rerun both commands, inspect the final diff and report actual results. Browser checks must be marked NOT RUN unless actually performed. Do not publish or deploy.

根因是 Completed 使用 !task.completed,与 Active 一样选未完成;正确条件是 task.completed。只需把该分支改成下列一行,不要连 Active 的 ! 也删除。若只把下拉选单的标签交换,画面有时看起来合理,但 repro 仍会失败;这说明修表象与修行为是两件事。

参考修正:Completed 分支 · javascript
if (filter === "completed") return tasks.filter((task) => task.completed);

步骤 4:用同一证据做回归

修正后 node repro.mjs 应印出 ["a"] 与 Reproduction passed,退出码为 0;原测试应 3 项全过。再依第一步相同操作重测画面:Completed 只有 Read,Active 只有 Build,All 保留两笔。先用相同输入证明原错误消失,再新增空清单与取消完成等边界,不要一开始换整批资料而失去前后比较。

证据修正前修正后
最小重现b,assertion 失败a,退出码 0
原本核心测试2 过 1 败3 过 0 败
Completed 画面BuildRead
Active/All需记实际结果Build/两笔皆在
尚未做的检查明列未执行不自动改成通过

最后看 core.mjs 的差异,确认没有改 addTask、decodeTasks 或测试期待。若对方回报修好了却没显示执行结果,要求命令、退出状态及失败摘要;不能执行时就记原因。两个测试通过也不能取代真正画面检查,要由你或具备浏览器工具的代理完成,并标明平台与预览网址。

补验取消完成与空清单

原重现已通过后,另建 regression.mjs,贴上下面程式,再执行 node regression.mjs。它先验证 Completed 的 a,取消 a 的完成状态后验证 Completed 为空、Active 保留 a/b,并检查原输入未被改动与三种空清单。预期印出 Regression passed,退出码 0。它是独立断言程式,不会把原 node --test core.test.mjs 的测试数自动增加。

档案:regression.mjs · javascript
import assert from "node:assert/strict";
import { toggleTask, visibleTasks } from "./core.mjs";

const tasks = Object.freeze([
  Object.freeze({ id: "a", title: "Read", completed: true }),
  Object.freeze({ id: "b", title: "Build", completed: false }),
]);
const ids = (items, filter) => visibleTasks(items, filter).map((task) => task.id);
assert.deepEqual(ids(tasks, "completed"), ["a"]);
const changed = toggleTask(tasks, "a");
assert.deepEqual(ids(changed, "completed"), []);
assert.deepEqual(ids(changed, "active"), ["a", "b"]);
assert.deepEqual(ids(changed, "all"), ["a", "b"]);
assert.deepEqual(tasks.map((task) => task.completed), [true, false]);
for (const filter of ["all", "active", "completed"]) {
  assert.deepEqual(ids(Object.freeze([]), filter), []);
}
console.log("Regression passed.");
终端机:执行边界回归 · sh
node regression.mjs

原 broken/core.mjs 还原练习也保留 regression.mjs;它应再次以非零状态失败,与 repro.mjs 的 b 一致。若你另外更动测试、标签或保存流程才让结果转绿,回到保存的原档重新做单一修正,并在标示这次被舍弃的假设。完整回归仍需实际画面与重载检查,未做就保留未执行。

排错习惯、还原与交付

一次只改一个可验证的假设,失败时把「做了什么、得到什么」追加到报告,避免下一个任务再次重试相同无效修正。若根因不在本篇预设位置,保留新证据并重新缩小范围,不因为教学说一行就硬改一行。真实专案的计时、帐号及网路条件可能造成不同故障,重现资料应先去除私人内容再交给 Codex。

交付包含 Bug 报告、最小重现、原因、限定差异及回归表。要重做时,停止自己的预览,只把原 broken/core.mjs 复制回来,保留 repro.mjs;它应再次失败,原测试回到 2 过 1 败。需要完整功能案例时接。图中 1 是重现,2 是定位修正,3 是回归;参考修正可本机验证,Codex 实际对话和各平台操作仍要依你的执行记录判定。

20. 修复 Bug 的完整流程 — 实作顺序示意图,非产品介面截图。 Reproduce → Fix → Regression
20. 修复 Bug 的完整流程 — 实作顺序示意图,非产品介面截图。 Reproduce → Fix → Regression · 图片:Mokaair (© Mokaair)
阅读完整文字说明

Reproduce to Fix to Regression

回总目录

  • 生活分享

    Codex 学习中心:完整教程目录

    从安装、第一个任务到 MD 规则与进阶集成,规划 60 篇 Codex 教程、十个单元。按程度、平台、需求或命令搜索下一篇;尚未公开的教程会标示状态,方便安排学习路线。

  • 生活分享

    Worktree 与多任务隔离

    Worktree 让同一个 Git 程式库有不同的工作目录,各自承接不同分支。它适合让两项工作分开改档,但资料库、连接埠与外部服务仍可能共用,不能把档案隔离当成所有资源隔离。

  • 生活分享

    实战:制作小网站

    从 brief.md 规划并制作 Small Steps 待办网站,完成新增、完成、删除、筛选与本机资料保存。将 HTML、CSS、资料函式、画面事件与测试分开,以 Node 测试和浏览器操作验收,并留下可重新启动与还原的交接纪录。

  • 生活分享

    用量与效率:减少重工

    记录任务条件、模型选项、时间与成果,找出能减少无效重试和过多上下文的调整。

最新旅游情报攻略

资料来源

生活分享