Use Cases (更新: 2026/6/3)

Claude Code 调试工作流:观察、复现、修复、回归测试

用 TypeScript、Node、Vitest 和 Claude Code 完成调试、复现、修复、回归测试与 CTA 检查。

Claude Code 调试工作流:观察、复现、修复、回归测试

Claude Code 可以根据错误信息给出修复建议,但真正的调试不应该只追求“看起来修好了”。可靠的流程要分开观察、假设、最小复现、修复和回归测试。省略这些步骤时,bug 可能在一个页面消失,却从另一个输入、语言版本或发布路径回来。

本文用 TypeScript、Node 和 Vitest 演示具体做法。需要保存失败条件时,配合 Claude Code and TDD;异常模型不清楚时,配合 error handling patterns;验证命令先失败时,配合 build error triage loop

给 Claude Code 明确的调查顺序

不要只说“修复这个错误”。要提供完整错误、stack trace、复现步骤、输入数据、期望结果、实际结果和最近修改文件。再要求 Claude Code 在改代码前列出三个原因假设。这样它会先区分事实和猜测,而不是直接写一个看似合理的补丁。

观察记录已知事实,假设解释可能原因,最小复现把假设变成失败测试或脚本,修复保持范围小,回归测试留在仓库里。这个顺序能让 reviewer 看到为什么改,而不只是看到改了什么。

{
  "name": "claude-debug-lab",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "vitest run",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "typescript": "^5.6.0",
    "vitest": "^3.0.0"
  }
}

例1: 把 undefined map 错误变成规则

第一个问题很常见:数据还没到,代码就调用 map。目标不是只消除崩溃,而是写下规则:缺失 payload 返回空列表,空名字被排除,有效名字会 trim。

export type User = {
  id: string;
  name?: string | null;
};

export function normalizeUsers(users: User[] | null | undefined): string[] {
  if (!Array.isArray(users)) return [];

  return users
    .filter((user): user is User & { name: string } => typeof user.name === "string")
    .map((user) => user.name.trim())
    .filter((name) => name.length > 0);
}
import { describe, expect, it } from "vitest";
import { normalizeUsers } from "../src/normalize-users.js";

describe("normalizeUsers", () => {
  it("returns an empty list when the API payload is missing", () => {
    expect(normalizeUsers(undefined)).toEqual([]);
    expect(normalizeUsers(null)).toEqual([]);
  });

  it("keeps only usable display names", () => {
    expect(
      normalizeUsers([
        { id: "u1", name: " Masa " },
        { id: "u2", name: "" },
        { id: "u3", name: null },
      ]),
    ).toEqual(["Masa"]);
  });
});

可以这样提示 Claude Code:

出现 Cannot read properties of undefined (reading 'map')。
normalizeUsers 必须容忍缺失 API payload,并移除空白 display name。
请先添加失败的 Vitest,再做最小修复。
最后运行 npm test 和 npm run typecheck。

常见陷阱是只写 users ?? []。它可能阻止崩溃,但 null name、空字符串、非数组 payload 的产品行为仍然没有定义。把业务规则告诉 Claude Code,修复和测试才会一致。

例2: 调试 async retry,不隐藏最后错误

异步 retry 的 bug 常常像“偶尔失败”。好的测试要确认调用次数、等待行为、最终成功和全部失败。如果最后错误被吞掉,事故排查时症状就不会指向真正失败的服务。

type RetryOptions = {
  times: number;
  delayMs: number;
  sleep?: (ms: number) => Promise<void>;
};

const defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));

export async function retry<T>(
  task: () => Promise<T>,
  { times, delayMs, sleep = defaultSleep }: RetryOptions,
): Promise<T> {
  let lastError: unknown;

  for (let attempt = 1; attempt <= times; attempt += 1) {
    try {
      return await task();
    } catch (error) {
      lastError = error;
      if (attempt < times) await sleep(delayMs);
    }
  }

  throw lastError instanceof Error ? lastError : new Error("Retry failed");
}

让 Claude Code 写测试时,要说明 mock 状态不能在测试之间泄漏,不要做大范围重构,并且必须保留最后的错误。调查时可以添加临时日志,但最终补丁中要删除,除非产品明确需要结构化日志。

例3: 先用最小复现固定日期边界

第三个例子是日期边界。页面上看起来像“3月导出少了3月31日的订单”,但根因通常不在按钮,而在所选月份开始时间和下个月开始时间的比较条件。把这个逻辑切成函数测试,比只给截图更容易让 Claude Code 找到原因。

export type Order = {
  id: string;
  createdAt: string;
  total: number;
};

export function exportMonthlyOrderIds(orders: Order[], month: string): string[] {
  const [yearText, monthText] = month.split("-");
  const year = Number(yearText);
  const monthIndex = Number(monthText) - 1;
  const start = new Date(Date.UTC(year, monthIndex, 1));
  const end = new Date(Date.UTC(year, monthIndex + 1, 1));

  return orders
    .filter((order) => {
      const createdAt = new Date(order.createdAt);
      return createdAt >= start && createdAt < end;
    })
    .map((order) => order.id);
}
import { describe, expect, it } from "vitest";
import { exportMonthlyOrderIds } from "../src/export-orders.js";

describe("exportMonthlyOrderIds", () => {
  it("includes orders from the first day through the last moment of the month in UTC", () => {
    const orders = [
      { id: "feb-end", createdAt: "2026-02-28T23:59:59.999Z", total: 1000 },
      { id: "mar-start", createdAt: "2026-03-01T00:00:00.000Z", total: 2000 },
      { id: "mar-end", createdAt: "2026-03-31T23:59:59.999Z", total: 3000 },
      { id: "apr-start", createdAt: "2026-04-01T00:00:00.000Z", total: 4000 },
    ];

    expect(exportMonthlyOrderIds(orders, "2026-03")).toEqual(["mar-start", "mar-end"]);
  });
});

提示 Claude Code 时要写清楚:不要依赖本地时区解析,包含所选月份的开始,不包含下个月的开始。这样它不会用 new Date("2026-03") 这类在不同环境中可能产生差异的写法。

可复制的调试提示词

目标:
  找到原因,添加回归测试,并用最小有效 diff 修复。

观察:
  - 完整错误:
  - 复现步骤:
  - 期望结果:
  - 实际结果:
  - 最近修改的文件:

限制:
  - 改代码前列出三个假设
  - 不做大范围重构
  - 不用 any 隐藏类型错误
  - 临时日志最后要删除
  - 最后运行 npm test 和 npm run typecheck

报告:
  - 根因
  - 修改文件
  - 新增回归测试
  - 剩余风险

这样 Claude Code 会成为调查伙伴,而不是只生成 patch。reviewer 可以先看到根因、证据和剩余风险。团队使用时,把这些字段放进 review gate,让 AI diff 和人工 diff 使用同一标准。

调试时不要破坏收入路径

公开网站的调试还要检查 CTA。内容修复可能把免费 PDF 表单推到不可见位置,改掉 Gumroad 链接,或让咨询路径更难找到。文章越热门,越要把收入导线当作调试范围的一部分。

可以用一个小规则固定分流。

const debuggingRoutes = {
  first_error: "free_pdf",
  repeated_bugfixes: "prompt_templates",
  setup_or_ci_blocked: "setup_guide",
  team_process_blocked: "consultation",
};

export function chooseDebuggingCta(intent) {
  return debuggingRoutes[intent] ?? "free_pdf";
}

console.log(chooseDebuggingCta("repeated_bugfixes"));

新手和比较读者适合 free cheatsheet。重复调试和 review 适合 50 Prompt Templates。权限、CI/CD 和设置问题适合 Setup Guide。团队导入和运营设计适合 咨询

本文已验证的内容

这次重写保留了正常 UTF-8 正文、可执行代码块、内部链接、外部链接,以及免费 PDF、Gumroad、咨询路径。下一步观察这个调试 slug 带来的 PDF 注册、Prompt Templates 点击、Setup Guide 点击和 Training 页面访问。

发布后的调试检查记录

发布调试文章时,不要只看代码是否正确。要打开公开 URL,检查 h1、canonical、正文开头、hero image、免费 PDF 表单、Gumroad 链接和咨询链接。热门文章里的调试流程改进,会直接影响读者下一步。如果说明更清楚了,但 PDF 不能注册、Gumroad 商品不对、咨询入口不清楚,收入路径仍然没有完成。

多语言版本可以共享代码例子,但解释和 CTA 必须是目标语言。中文读者应该能用中文理解观察、复现、修复、测试的顺序。截图检查时,要看正文开头、prompt 模板附近和 CTA 附近。标题翻译但正文或 CTA 仍是英语,会让新手停止操作。

下一步关注这个 slug 带来的免费 PDF 注册、Prompt Templates 点击、Setup Guide 点击和 Training 页面访问。debugging 读者通常已经有明确痛点,所以比 PV 更重要的是他们进入了哪条导线。下一次让 Claude Code 改写时,先给这些数字,再决定补充正文、调整 CTA 优先级或改 Products 页面卡片。

调试文章的读者通常会立刻尝试代码。因此,代码语法、prompt 顺序、失败例和最后要看的指标都要清楚。读者看完后应该知道先贴什么错误、先写什么测试、什么时候该看 Gumroad 教材或预约咨询。这样文章才不是普通信息,而是实际工作的入口。

如果数字没有增长,要先看摩擦。免费 PDF 表单是否太远,Prompt Templates 的说明是否符合 debugging 读者的痛点,Setup Guide 和咨询是否放在团队导入的上下文里。调试读者的问题意识很强,只要 CTA 文脉正确,小修改也可能带来注册或购买。

#claude-code #debugging #troubleshooting #tests #workflow
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。