搜索/让AI在大型代码库中做出经过测试、可直接评审的改动

让AI在大型代码库中做出经过测试、可直接评审的改动

在让AI智能体修改大型多语言代码库时使用。它通过项目的封装命令构建,把测试放在对应代码旁并确认改动前测试会失败,遵守评审规则,只汇报自己实际运行看到的结果。

要使用这个AI规则
## 只通过项目的封装命令构建和运行测试 大型项目通常会把编译器和测试运行器封装进一个统一的项目命令中,该命令会在运行任何内容之前重新编译并注入你的本地改动。务必始终通过这个封装工具进行构建和运行。绝不要直接调用原始的测试运行器或之前编译好的二进制文件,因为那样执行的是不包含你改动的过期产物,即便测试通过也说明不了任何问题。 要弄清楚哪些改动可以跳过原生重新构建。只涉及非编译输入的改动——比如类型声明,或是能自行重新加载的打包脚本——并不需要完整构建,强行执行完整构建只会浪费时间;针对这类改动,直接运行更轻量的定向检查即可。 不要给完整构建设置超时限制。一次正常的冷构建可能耗时较长,中途强行终止只会产生令人困惑、具有误导性的失败结果。当封装工具会把末尾的参数转发给构建出的程序时,要把构建相关的标志放在这些运行参数之前,以确保参数路由不产生歧义。 ## 把测试加到所改代码已有的测试文件里 默认情况下,应把新测试添加到你所改动代码对应的现有测试文件中。某个模块行为中的bug,应该归入该模块现有的测试文件,而不是新建一个文件。把测试放在相关覆盖范围旁边,才能让它易于被发现,并避免重复搭建测试环境。 要遵循代码库已有的测试布局:按子系统分组的单元测试、兼容性测试、平台与Web API测试、命令行测试,以及端到端集成测试,各自都有专属区域。把你的测试放在已经存在同类覆盖的位置。 专用文件夹只能用于它本来设计的那种情形。以问题编号命名的回归测试文件夹,只能用于真正的回归问题,也就是在之前版本中原本正常、后来才被破坏的行为,而且这个编号必须是真实存在的,绝不能用占位符代替。如果某个行为从来都不曾正确过,那就不算回归,相应的测试应该放进该模块的普通测试文件中。 ## 编写每次运行结果都一样的测试 对于大段输出,优先使用快照断言,而不是脆弱的相等性检查,并对快照做归一化处理,避免临时路径之类的偶然值造成不必要的频繁变动。绝不要编写只检查"没有崩溃"或"没有出现未处理异常字符串"的测试;这种测试在流水线中永远不会失败,只会带来虚假的安全感。 要消除一切不确定性来源。不要硬编码网络端口;应绑定一个临时端口,再读取系统实际分配的端口号。绝不要用sleep或定时器去等待某个结果,因为你要测试的是条件本身,而不是时间的流逝;应改为等待实际条件的达成。使用测试框架自带的临时目录辅助工具,而不是手动创建临时目录,并且在测试中要避免使用文件查找、文本查找等shell工具,而应使用项目自身的文件API。 当测试启动一个子进程时,要先断言它的输出内容,再断言它的退出码,这样失败时能给出有用的信息,而不是只有一个光秃秃的非零状态码。 ## 确认新测试在改动前会失败,只汇报实际运行的结果 一项改动在经过测试之前都不算完成。如果你没有运行测试,就应当假定代码是不能工作的;运行测试是完成工作本身的一部分,而不是可有可无的后续步骤。 要证明每个新测试确实覆盖到了你的改动:它在未修改的基线代码上必须失败,在你的构建上必须通过。一个在没有你的改动时就已经通过的测试,什么也证明不了,所以在信任它之前,务必对这两个方向都加以确认。 在每一条提交信息、每一次评审回复、每一次状态更新中都要保持谦逊和诚实。绝不要夸大自己完成的工作或实际生效的内容。只汇报你亲自运行后观察到的结果,并明确说明哪些部分尚未验证或尚未完成,而不要暗示工作已经全部完成。 ## 修改前先弄清代码库的结构 在动手编辑之前,先了解代码库的组织方式:哪一层负责哪部分职责、共享工具代码放在哪里,以及哪些文件是自动生成的、哪些是手写的。生成文件是由源定义产生的,所以应该编辑源文件,让构建过程重新生成它们;绝不要直接手动编辑生成出来的文件,因为下一次构建就会把它覆盖掉。 要确定你所改动的行为归属于哪个子系统——无论是解析、模块解析、运行时API、网络、存储、打包工具,还是包管理器——这样才能让你的改动和对应的测试都落在正确的位置。 要遵循现有的代码风格。查看相邻文件中已经确立的写法模式并加以匹配,而不是把别的项目里的惯例照搬过来。优先使用该语言自身的资源管理惯用法,比如基于作用域的自动清理机制,而不是手动释放资源,并且要尊重文档中记载的边界情况,例如某些在重置时会跳过析构函数调用的区域中分配的值,必须先显式释放。 ## 阅读评审规则,遵守项目的强制规范 成熟的项目会把评审者用来阻止合并的那些标准,提炼成一份成文的规则集。在写出任何做出不明显选择的代码之前,先阅读这份规则;在处理特定领域的工作之前,也要先阅读该领域对应的情境指南,比如兼容层、面向用户的API设计、性能敏感的热点路径、按平台区分的代码、依赖与第三方库变更,或是文档与类型声明。 要严格匹配项目强制要求的规范,因为自动化流水线会强制执行这些规范。使用规定的分支名前缀,保持代码注释简短,更深入的说明应移到文档中,且只在明确要求时才撰写;在文件操作中使用绝对路径。当你做出针对特定平台的改动时,要在所有受支持的目标平台上都进行编译,因为条件编译的代码只有在对应目标平台真正被构建时,才会进行类型检查。 ## 构建失败时用项目的诊断工具,工具给出误导信息就修好它 当自动化构建失败时,应使用项目专用的诊断命令——那些能够呈现失败测试、汇总任务状态、保存完整日志的命令——而不是靠自己手动拼凑出全貌。这些工具已经把新出现的失败与其他地方也存在的失败区分开,并过滤掉了常规噪音。 在查看对某项改动的反馈时,要使用能返回完整信息的命令。普通的列表往往会悄悄遗漏评审摘要和逐行评论,所以应优先使用那种能把顶层评论、评审意见和行内评论一起按时间顺序、带标签整合展示的工具。 如果某个辅助工具的输出看起来不对——比如注解被错误解析,或是某个字段的上游数据结构发生了变化——应该直接修复呈现工具本身,而不是在下游绕过这个问题。这个辅助工具只是底层工具外面的一层薄封装,修复它才能让之后每一次运行都保持正确。