用测试夹具约束 Agent:给定失败用例,要求只输出最小 diff 的提示词套路

「帮我修一下这个测试」是 Agent 上下文里最高危的句子之一。没有夹具、没有失败断言、没有路径白名单时,模型会倾向于:改生产代码 + 改测试 + 顺手重构,最后给你一个「全绿」但不可审的大补丁。

反过来,把 失败用例当作合同 :先复现为红,再要求 只输出最小 diff,Agent 的行为会收敛得惊人。本文给可复制的提示词套路与验收清单,可与同日「子 Agent 委派」文联用。

核心思想

红测是输入,不是修完再补。

最小 diff 是工程礼貌,也是 Token 与评审成本的节约。

提示词里的「禁止项」与「交付格式」比形容词「请小心」更有约束力。

夹具驱动修复流

  1. 复现:本地跑出红;保存命令、关键断言、栈顶。
  2. 提示:粘贴失败材料 + 路径范围 + 禁止项 + 交付格式。
  3. 改码:只允许触达白名单文件。
  4. 审阅:人工或主 Agent 扫 diff;重跑目标测与邻近测。

不要在「还没复现」时让 Agent 开改------那会把猜测写进仓库。

弱提示 vs 强提示

弱提示:

登录测试挂了,帮我修一下,顺便看看相关代码有没有问题。

后果:范围爆炸、测试被改宽、生产逻辑被「简化」。

强提示:

下列失败是唯一目标。先阅读夹具与断言,再改代码。

允许修改:src/auth/token.py

禁止:修改任何测试文件;禁止格式化无关文件;禁止新建抽象层。

验收:pytest tests/test_token_expire.py -q 从失败变全绿。

交付:仅 unified diff + 变更说明不超过 5 行。

强约束换来可审阅补丁。

提示词套路五段(复制填空)

text 复制代码
【背景】
命令:pytest tests/test_xxx.py -q
当前结果:失败(将完整失败摘要粘贴于下)
目标:使上述命令通过;不追求「更大重构」。

【材料】
- 失败断言与期望值:(粘贴)
- 夹具路径:tests/fixtures/...
- 相关实现:@src/...(仅这些)

【范围】
允许修改:
- src/a.py
禁止:
- tests/**(除非我显式允许)
- 全文件格式化、重命名扫射、新增依赖

【交付】
1. 变更文件列表
2. unified diff(或按工具显示的补丁)
3. 不要长文解释;必要说明 ≤ 5 行

【验收】
重跑:pytest tests/test_xxx.py -q
期望:全绿。若无法在范围内修复,停止并说明阻塞,不要扩大范围。

把这五段存进团队 Prompt 库 / AtomGit,比每次临场发挥稳定。

实战演练:过期 Token 断言

假设失败为:expected status 401, got 200,夹具是过期 JWT。

操作顺序:

  1. 你先本地复现,确认不是环境抖了一下。
  2. 用五段提示词,只 @ token 校验实现与失败测试输出(测试文件只读引用,不授权修改)。
  3. 若 Agent 提议「改测试期望为 200」------直接拒绝:合同是生产行为对齐断言,不是断言投降。
  4. 若 Agent 想引入新库处理 JWT------要求先在无新依赖前提下修复;新依赖单开一张任务卡。

最小 diff 的审阅要点

  • 失败用例已先本地为红
  • diff 仅触及约定文件
  • 无格式化大扫除 / 重命名扫射
  • 目标测转绿,邻近测未误伤
  • 提交信息指向夹具与意图(如 fix: reject expired token (test_token_expire))
  • 套路模板入库

审阅时用 git diff --stat 一眼看体积;单个「修测试」提交动到 20 个文件,多半违例。

与委派、排障的衔接

  • 委派:每张子卡的验收命令,最好就是一条红测转绿;夹具套路是卡内提示词。
  • 排障(10-07):乱改类故障,用本套路的路径白名单与「禁止改测」刹住。
  • Manual 精修(10-05):Agent 给出最小 diff 后,高风险行用手改。

何时允许改测试

例外要显式写进提示词,例如:「夹具数据过期,允许只改 tests/fixtures/expired.json 的时间戳,不允许改断言语义。」

默认 不允许改测试,是为了防止 Agent 用「改期望」骗绿。

反模式速查

反模式 问题 替代
先改码再补测 合同后补,易空转 先红测
允许改全仓 必扩写 白名单
要求「详细设计文档」 Token 浪费 限 5 行说明
多失败一次修 纠缠 一测一卡
绿了就不看 diff 藏重构 强制 --stat

夹具的三种形态

  1. 单元夹具:函数输入输出、临时文件、工厂函数。
  2. 契约夹具:固定 JSON / 录制过的响应(注意脱敏)。
  3. 失败快照 :一次真实失败的断言消息与栈顶(可进 artifacts/ 但不含密钥)。

喂给 Agent 时,优先「断言原文 + 最小相关源码」,不要整份 HTML 报告。

多失败如何排队

一次会话只修一个红。排序建议:

  1. 纯逻辑、无 IO 的失败;
  2. 有夹具可稳复现的;
  3. 涉及时间/网络的(先固定时钟或 mock)。

每个失败一张卡,修绿后提交,再开下一张。禁止「顺便把整个文件的 flake 都消掉」------那是重构项目,另开需求。

当 Agent 给出「正确但过大」的 diff

处理流程:

  1. 肯定其理解的断言语义;
  2. 要求在同一语义下重写为更小补丁(点名删掉的文件/ hunk);
  3. 仍过大则改 Manual:只采纳关键 hunk;
  4. 把「体积上限」(例如不超过 N 个文件)写进下一轮提示。

体积上限是经验值,可按模块调整,但要有数字,不能只说「小一点」。

提示词库的版本化

docs/prompts/min-diff-from-fixture.md 应有简短变更记录:何时加了「禁止改测」、何时加了交付格式。Agent 提示词也是代码------会腐朽、会分叉。AtomGit 上的评审可以像改代码一样改提示词。

与 CI 的关系

本地红测转绿后,CI 仍可能因环境差失败。提示词可加一句:「若修复依赖环境变量,必须在 PR 描述列出,不得把秘密写进测试。」夹具约束的是 Agent 行为;CI 约束的是合并门禁------两层都要。

练习题(可当作工作坊)

给队员一个故意写错的 apply_discount 与红测,只允许改实现文件。评分看:--stat 是否干净、是否改测骗绿、提交信息是否指向夹具。比听分享课更管用。

端到端示例对话(缩写)

你: (粘贴五段套路,附失败断言 assert apply_discount(100, 0) == 100 实际得到 0)

**Agent:**提议同时重构折扣体系并改三处调用。

**你:**驳回。范围仅 pricing/discount.py。禁止改调用方。再给最小 diff。

**Agent:**只在 percent is None 与 percent == 0 分支修正。

你: pytest tests/test_discount.py -q 全绿;--stat 仅一文件。提交。

关键教学点:第一次草案被驳回是成功排障,不是失败。夹具合同给了你驳回的依据。

「只输出 diff」在不同工具里的落地

  • Cursor Agent:要求补丁摘要 + 文件列表;用 Git 面板审。
  • Manual:只应用相关 hunk。
  • Aider:审 diff 后再提交。
  • 纯聊天导出:要求 fenced diff,你手动应用------更慢但最可控。

套路五段跨工具复用;改变的只是粘贴位置。

夹具脱敏清单

放入提示词前检查:

  • 无真实邮箱/手机/身份证;
  • 无内网 URL 若属敏感;
  • 无 Token/Session;
  • 客户名已替换为 acme。

否则「最小 diff」过程可能把敏感信息送进模型与日志。安全基线与提示词套路必须绑在一起。

度量提示词是否变好

记录 20 次修复:

  • 平均触达文件数;
  • 驳回次数;
  • 是否改测骗绿。

若触达文件数下降、骗绿为零,说明套路生效。把统计贴进团队周会,比分享「我觉得有用」更有说服力。

扩展:属性测试与 Agent

若你用属性测试(hypothesis 等)发现失败输入,把那组输入写成最小夹具再喂 Agent,往往比丢整段理论说明更有效。合同依旧是「这一输入从红到绿」,不是「请理解属性测试框架」。

与 Rules 的配合

在 .cursor/rules 或等价物中可放短铁律:

  • 修复测试失败时默认禁止修改测试文件,除非用户显式允许;
  • 交付必须包含变更文件列表;
  • 禁止以「代码风格」为由改动无关文件。

铁律保持一屏;详细五段套路放 Prompt 库按需 @。Always 过长会引入新的前缀税,与「最小 diff」目标相悖。

红测无法本地复现时

若只在 CI 红:

  1. 先下载 CI 日志关键段;
  2. 尝试在同版本容器/同环境变量下复现;
  3. 仍无法复现则开「调查卡」,目标是复现,不是改码;
  4. 复现成功后再开「修复卡」。

把调查与修复拆开,避免 Agent 在未复现时大面积「猜修」。

提交前最后 60 秒

  • git diff --stat
  • 目标测命令
  • 邻近测或模块测
  • 扫一眼是否出现锁文件/快照无意变更

六十秒检查能拦下大半「最小 diff」名不副其实的提交。

给评审者的留言模板

text 复制代码
类型: 夹具约束修复
红测: tests/test_xxx.py
策略: 禁止改测 / 白名单文件
验证: (粘贴命令输出)
风险: 无 API 变更 / 有(说明)

PR 上这几行,比「请看」更尊重评审时间。

提示词完整粘贴版(可直接用)

下面把五段合并为一块,方便存库。花括号内替换:

text 复制代码
你正在修复一个已复现的失败测试。先读材料,再改代码。

背景:命令 `{cmd}` 当前失败。失败摘要:
{failure_log}

材料:夹具 `{fixture_path}`;只读参考 `{ref_files}`。

范围:允许修改 {allow_paths}。禁止修改测试文件与 {deny_paths};禁止全文件格式化、重命名扫射、新增依赖。

交付:1) 变更文件列表 2) unified diff 3) 说明≤5行。不要长文。

验收:重跑 `{cmd}` 必须全绿。若范围内无法修复,停止并报告阻塞,禁止自行扩大范围。

把该块放进 docs/prompts/min-diff-from-fixture.md 后,团队新人第一周就能按同一合同工作。再配上 --stat 审阅与「改测必须显式授权」,骗绿与扩写会显著下降。若 Agent 第一次仍过大,用同一合同驳回并加「体积上限:最多 N 个文件」------数字写进提示,比「再小一点」有效。夹具是合同,diff 是履约;履约可驳回,合同却要稳定,不要每轮改口径。

FAQ

Q:最小 diff 会不会阻碍必要重构?

A:会刻意阻碍「夹带重构」。必要重构单开需求卡,带自己的测试与评审,不混在故障修复里。

Q:测试本身有 bug 怎么办?

A:显式授权改测,并在提示词写清「允许改哪个断言、不允许放宽什么语义」。默认禁令是为了防骗绿,不是教条。

Q:多模块失败能否并行?

A:文件无交集时可并行;否则串行。并行时每张卡独立合同,互不共享脏历史。

Q:要不要让 Agent 先写计划?

A:可以,但计划阶段只读;计划通过后再授权改码。计划不等于可以扩写范围。

把 FAQ 收进文末,读者检索「骗绿」「重构」时更容易落地。实践上,合同稳定比模型更换更能降低翻车率;夹具驱动是把测试重新放回驾驶席。

边界声明

  • 示例框架名(pytest 等)可替换为你的栈;原则不变。
  • 不提供破坏测试体系或伪造覆盖率的技巧。

今晚可执行

  1. 挑一个当前红测,跑通复现。
  2. 用五段套路发一次 Agent 请求。
  3. 用 git diff --stat 验收是否最小。
  4. 把套路存 docs/prompts/min-diff-from-fixture.md。

夹具是合同,diff 是履约;写不清合同,就不要怪 Agent 乱履约。

相关推荐
码云之上3 小时前
把网页变成可引用知识——Chatbot 联网工具
人工智能·架构·agent
山顶夕景3 小时前
【Agent】自进化Dream-RSI
大模型·agent·自进化
王中阳Go3 小时前
自己摸了 2 个月零 offer,补底子只用了 3 块:Go 后端转 AI 最难的不是技术
后端·agent·ai编程
挖掘狂人6 小时前
从 "调模型" 到 "搭系统":Harness Engineering 凭什么成为 2026 年 AI 圈最热的新词
人工智能·agent·ai编程
Flynt7 小时前
这个日增 1400 星的 E2E 框架说"第二次跑不调模型",我改了按钮文案试了试
agent·ai编程·测试
镜舟科技7 小时前
从 StarRocks 到 MIP:数据平台的下一步是“理解”
starrocks·sql·ai·prompt·agent·context·mip
XLYcmy7 小时前
PDF 论文处理器 — 改进方向与建议文档
python·pdf·llm·agent·dify·rag·harness
小范的技术工坊8 小时前
Agent VS Workflow?
大模型·agent
hpoenixf9 小时前
一句“帮我看看我基金组合”,怎样走过 ETF Agent 的六层系统
agent