chimera-prove-the-test-discriminates
一个你从没见它失败过的回归测试只是猜测。提交之前,把代码重新弄坏,看着它变红。
由读过该卡片的评审者赋予,而不是文件自我声明的。智能体在处理不可信内容的运行中提炼出的卡片,生来即被标记为受污染,在被检索之前会一直等待评审。
何时会想到它
- 写了一个回归测试
- 修完 bug 顺手加了测试
- 测试过了就发吧
- 修好之后再补测试
价值通常在「避免」和「检查」里。「该做」是人人都会写的那一节。
上面的卡片正文是译文。英文原文才是 CLI 导入的内容、智能体运行时读取的内容,也是下方哈希所证明的内容。
触发
你修好了一个 bug,并写了一个测试让它不能再回来。测试通过了。这就是你全部的证据,而如果这个测试对这个 bug 什么都没断言,你手上的证据也一模一样。
当测试是在修复之后写的时候,这条最要紧,因为那时这个测试跑过的唯一代码,就是 bug 已经不在的代码。对于在 TDD 循环里先写、见过红的测试,这条就没那么要紧——你已经亲眼看过它失败,而那正是这个循环的全部意义。
对于真正的新行为的测试,这条不适用,因为那里没有可以回退到的"之前"。在那种情况下,有区分力的检查是另一回事:删掉新的实现,确认测试是因为它不存在而失败,而不是因为某个 bug。
该做
- 找出构成这次修复的那处确切编辑——是那个 hunk,不是那次提交。如果修复就是改了一处比较,那这处比较就是你要撤销的东西。
- 撤销它。用
git stash把修复藏起来,或者手工把那一行改回它坏掉的样子。 - 只跑那个新测试:
pytest tests/test_thing.py::test_the_regression -x。 - 读那条失败信息。它必须是你写的断言在失败,并且信息是关于那个行为的——不是
SyntaxError,不是收集错误,也不是一个改到一半的文件抛出的ImportError。那些是因为错误的原因而变红,对这个测试什么都证明不了。 - 把修复恢复回来(
git stash pop),确认同一个测试现在通过了。 - 把这个事实写进测试的 docstring:撤销了什么,以及失败时是什么样子。下一个碰这个测试的人,需要知道它曾经真的对着 bug 跑过。
避免
断言那些在两个世界里都成立的东西。经典形状:
result = parse_config(raw)
assert result is not None
assert "timeout" in result
这个 bug 是 timeout 返回的是字符串 "30" 而不是整数 30。上面两条断言在哪种情况下都成立。有区分力的是那个变了的东西:
# 对——对着有 bug 的代码会失败
assert parse_config(raw)["timeout"] == 30
assert isinstance(parse_config(raw)["timeout"], int)
也要避免为了"让它快点失败"而通过注释掉整个函数或删掉一个 import 来做回退。那会产生一次红色运行,而这次红色对文件里任何一个测试都会发生,所以它对这一个测试什么都没说明。回退必须是那次修复,而且只是那次修复。
还要避免那种擦身而过的情况:测试是通过一条生产环境从不走的路径到达被修复的代码的——那是另一种失败,对应的卡片是 chimera-test-the-wiring-not-the-class。
检查
一个二元问题:你有没有亲眼看到这个测试在未修复的代码上,因为它自己的断言而打印出失败?
如果有,就完事了。如果答案是"它本来会失败的",那你什么都没检查过——那句话是一个预测,而它是由写出这个测试的同一套推理产生的。
机械化的做法:
git stash # 移除修复
pytest tests/test_x.py::test_regression # 必须是红的,而且红在你的断言上
git stash pop # 恢复
pytest tests/test_x.py::test_regression # 必须是绿的
先红后绿,两次都要亲眼看到,否则这个测试就是未经证明的。
风险
有些修复没法廉价地回退:一次依赖升级、一次 schema 迁移、一个被删掉的文件、一处对内置(vendored)库的改动。在那些地方硬要回退,代价可能超过这个测试本身的价值。诚实的退路是重建那个曾经能弄坏它的输入,并断言那个具体的值,然后在 docstring 里明说没有观察到红色运行——一个承认自己未经证明的测试,远好过一个暗示自己被检查过的测试。
这张卡片真正的危险,是你忘了撤销的那次回退。在一棵脏的工作树上做这套动作,正是一行被重新弄坏的代码会和它自己的回归测试一起被提交进去的方式,而测试套件是绿的,因为你把修复恢复到了错误的文件里。每一次提交前都跑一遍 git diff。
还有,一个有区分力的测试,好不过你对那个 bug 的理解。它证明的是这个测试能抓住这一次回退。它证明不了你修的是根因而不是症状,而把一次先红后绿的运行当成后者的证据,是一个证据撑不住的更大论断。
如何使用
卡片就是数据。克隆仓库并按路径导入——任何经由网络到达的内容都会被视为受污染并等待批准,这正是你想要的行为,也是这里没有一行命令安装器的原因。
git clone https://github.com/brcampidelli/chimera-agent.gitchimera skills-import chimera-agent/skills/chimera-prove-the-test-discriminates/SKILL.md完整性
文件发布版本的 SHA-256。导入方可以据此核对收到的内容与本页展示的一致。
90d4bf00eb67055008527ee372153b2637fa2feea601ed6760997eda239f0b76