ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hypothesis 代码评审手册:维护者视角的 Pull Request 评审流程与检查清单

Hypothesis 代码评审手册:维护者视角的 Pull Request 评审流程与检查清单 测试开发工具【免费下载链接】hypothesisThe property-based testing library for Python项目地址https://gitcode.com/gh_mirrors/hy/hypothesis点击查看免费下载Hypothesis 是 Python 生态中最具影响力的属性测试property-based testing库之一其代码库由hypothesis/src/下的 Python 实现、hypothesis/rust/下的 Rust 组件、配套的发布工具链与数千个测试用例共同构成。要让这样一个持续迭代、采用近乎每个合并即发布节奏的项目保持质量一套可执行的代码评审Code Review流程必不可少。本指南以仓库内 guides/review.rstThe Hypothesis Code Review Handbook为骨架结合发布工具链、设置系统与质量测试的真实源码完整讲解 Hypothesis 的评审范围、评审目标、分场景检查清单功能变更、公共 API、Bug 修复、设置变更、引擎变更以及如何优雅地请求更多工作帮助你以维护者或资深贡献者的身份完成一次合格的 Hypothesis 评审。文档定位给维护者而非使用者的评审手册guides/目录见 guides/README.md存放的是开发 Hypothesis 的人才需要的文档与面向使用者的主文档相互独立。review.rst开头就明确这是一份部分描述现状、部分规定做法的手册且承认流程会随实际情况不断演变entirely prone to change in response to circumstance and need. Were still figuring this thing out!。手册定义了评审的适用范围与基本机制需要评审的对象所有变更都必须获得至少一位除作者之外、拥有仓库写权限的人的签署sign off。合并时机一旦 CI 构建转绿build is green且评审者批准维护者团队中的任何人都可以合并该 PR。多重评审多位维护者可以但不必须评审同一变更任何维护者都可以通过 request changes 来阻止合并。分歧处理共识是理想状态但非强制。若部分评审者已批准、部分要求修改理想情况下应尽力处理全部意见但若评审者认为合适也可以驳回dismiss反对意见。手册也坦言实践中对意见不一的场景测试得还不多未来可能长出更明确的规则。评审的两个核心目标手册把评审目标高度凝练为两个问题所有检查清单都服务于它们这个变更会让用户的生活变糟吗这个变更会让维护者的生活变糟吗代码评审是作者与评审者之间的协作过程目标是对这两个问题都回答否。理想情况下变更当然还应让用户或维护者的生活变得更好但手册特意强调中性即可接受作者应当被假定有提交变更的充分理由因此只要变更大体无害、不造成长期负担就可以放行。这个宁缺毋滥但不过度苛求的基调是后续所有具体条款的哲学前提。社交因素评审也是一种社区协作手册专门列出一节社交规范强调评审发生在真实的人与人之间永远感谢外部贡献者理想情况下也感谢维护者。项目的行为准则Code of Conduct同样适用于 Pull Request 与 Issue必要时可以动用权限强制执行其内容见 hypothesis/docs/community.rst。任何人都欢迎做代码评审包括非维护者只有正式维护者才有权批准与合并 PR但外部评审同样有价值。这一定位意味着即便你没有写权限也可以依据本手册对 Hypothesis 的 PR 给出高质量评审意见。正交性Orthogonality一个 PR 只做一个用户可见变更手册对一次变更的粒度有硬性规定这是最容易在评审中被忽视、又最影响后续维护质量的一条minor 与 patch 版本强制规则是每次发布最多包含一个用户可见变更。major 版本允许打包多个变更但应拆成较小的 PR 合入某个跟踪分支tracking branch。手册坦诚我们目前在这方面做得并不好因此鼓励评审者格外严格、给出大量反对意见。什么算用户可见变更有一定主观性但应偏向于可能算就算err in the direction of assuming that if it might count then it does count。经验法则如果RELEASE.rst中出现了 additionally 一词或者需要用项目符号bullet points才能说清楚那么这个变更大概率太大了。非用户可见的变更同样理想情况下应自成一次发布但允许适度通融顺手做中等规模重构可以接受若一个 PR 完全不涉及发布没有RELEASE.rst则对正交性的要求不会那么高虽然依然提倡。RELEASE.rst是这条规则的实际落点它是位于 hypothesis/RELEASE.rst 的发布描述文件当前仓库中的实例如RELEASE_TYPE: patch 一行说明由发布工具链强制解析见下文发布工具链。描述清晰性Clarity of DescriptionRELEASE.rst中的描述必须说清楚两件事变更的动机motivation。变更可能的后果likely consequences。这不要求写成论文——若遵循了正交性要求一两段通常就够了。而任何对评审者有用的额外信息背景、为什么采用特定方案、对使用者不感兴趣的内部实现的引用应放在PR 评论中而不是塞进 changelog。这里隐含了一个分工RELEASE.rst面向最终用户会进入公开 changelogPR 评论面向评审者。评审时应当检查作者是否把这两类信息放对了位置。功能变更Functionality Changes检查清单只要改变了 Hypothesis 的行为就适用本节——经验法则碰了src下的文件就算。检查项如下代码在意图与行为上清晰clear in its intent and behaviour。行为变更必须配合适的测试来演示新行为。Hypothesis 绝不能 flaky。这里对 flakiness 有精确的定义测试失败但该失败并不指示 Hypothesis 或用户代码/测试本身有 bug。也就是说任何随机抖动导致的失败都是不可接受的。变更日志RELEASE.rst应 bumpminor 或 patch版本号细节见 guides/documentation.rst准确描述变更且不应提及仅内部使用的 API。对于复杂标记markup建议实际构建一次文档并人工检查 changelog 是否存在未导致编译错误但格式错误的问题。第 4 条中的构建文档在发布工具链中对应sphinx-build调用见 tooling/src/hypothesistooling/release.py 中的build_docs()使用--fail-on-warning把警告当错误处理。公共 API 变更最需要谨慎的评审公共 API 变更需要最仔细的审查因为它是维护者被绑定最久的承诺Hypothesis 遵循语义化版本semantic versioning而且不常发布新的 major 版本——一旦 API 定型就要长期负责。手册给出九条硬性要求所有公共 API 变更必须文档化。If its not documented, it doesnt count as public API!——没有文档就不算公共 API。变更必须向后兼容无法兼容时必须先引入deprecation 警告待 major 版本升级后才能移除警告与功能。被弃用的 API其弃用警告必须说清楚用户应如何改造代码可以引用文档。如果改造可被自动化则弃用必须附带一个codemod来修复或至少有一个写一个 codemod的跟踪 issue见下节请求更多工作。如果预计未来要做不兼容变更应尽可能在引入该 API 时就一次性做好而不是留到以后。API 对非法输入应给出清晰、有帮助的错误消息错误消息必须展示触发错误的值并尽量指明是它的哪个特征导致失败例如类型。错误用法绝不能静默失败——用户误用 API 时应得到显式错误。功能应限于长期易于支持的范围尤其要避免与当前 Hypothesis 内部实现过度耦合的功能。DRMacIver 或 Zac-HD 必须批准此类变更其他维护者也欢迎且很可能参与评审。必须遵循独立的 house API style 指南。第 3 条中提到的 codemod 机制在仓库中真实存在hypothesis codemod命令实现于 hypothesis/src/hypothesis/extra/codemods.py而其触发逻辑在 hypothesis/src/hypothesis/utils/deprecation.py 的note_deprecation()中当has_codemodTrue时警告消息会自动追加提示hypothesis codemod命令行工具可以自动重构你的代码以修复此警告。第 5、6 条错误消息与不静默失败在源码中同样有印证_settings.py中每个设置项都有专门的校验函数例如 hypothesis/src/hypothesis/_settings.py 的_validate_max_examples()会在max_examples 1时抛出InvalidArgument并给出包含实际传入值的可操作提示If you want to disable generation entirely, use phases[Phase.explicit] instead同文件 L524-L533 的_validate_backend()甚至会针对crosshair后端给出安装提示。这正体现了错误消息总是显示触发错误的值这一 API 评审要求。House API Style 速览API 评审要求遵守 guides/api-style.rst其要点包括公共 API绝对不允许子类化absolutely no subclassing as part of the public API。参数必须尽可能彻底校验用InvalidArgument拒绝坏参数而不是抛内部异常。大量使用默认参数有默认值的参数应设为keyword-onlymin_value/max_value例外。集合类策略的元素策略参数不应有默认值元素策略应放在前两个参数位置有序类型的界参数统一叫min_value/max_value集合大小参数统一为min_size默认 0与max_size默认 None。参数不应是值或策略二选一——如果用户想传值让他们用just包一层如果组合参数导致无法生成任何值应raise InvalidArgument而不是返回nothing()后者会静默削弱组合策略。错误尽量延迟到测试运行时抛出通常由defines_strategy装饰器自动完成而不是策略定义时。Bug 修复Bug Fixes的验收标准所有 Bug 修复必须带一个能在 master 上复现该 Bug、且在该分支上被修复的测试。如果提交者能令人信服地论证测试这个过于困难可以破例。可能的话能让类似 Bug 不再发生的修复更好治本优于治标。可能的话能同时捕获该 Bug 与其所属更一般类别的测试更好在更抽象层面钉死错误。这三条按修复质量从低到高排列复现测试是底线防止同类 Bug 是加分覆盖更广类别是最优。设置变更Settings Changes克制地把控设置项本节目前仅适用于 Python 版本。核心警告是Hypothesis 的设置对象很容易被当成什么都能往里塞的垃圾场而这会迅速让用户困惑必须小心避免。新增设置应满足用户能对它有有意义的意见。手册指出Hypothesis 很多已有设置其实只是把做正确事情的责任甩给用户。不参照 Hypothesis 内部实现也能理解。对应能在不同测试之间或同一测试的不同运行之间有意义地变化的行为——典型例子是 profile 系统CI 与本地开发可能需要不同的 Hypothesis 行为。如果任何测试套件的任何运行中都永远只会有一个值那它应该是某种全局配置而不是设置。这条全局配置 vs 设置的边界直接对应_settings.py中内置 profile 的划分settings.register_profile(default, ...)与settings.register_profile(ci, ...)定义了两种可切换的默认行为CI 环境下自动激活ciprofile见 hypothesis/src/hypothesis/_settings.py。例如defaultprofile 的max_examples100、deadline200ms而ciprofile 基于 default 派生仅覆盖derandomizeTrue、deadlineNone、databaseNone、print_blobTrue、suppress_health_check[HealthCheck.too_slow]——这正体现了同一设置在不同运行语境下取值不同的设计哲学。设置的弃用流程not_set哨兵与两阶段过渡手册规定了设置弃用的标准流程这是本文档中最具操作性的源码级细节弃用一个设置以待后续移除时把该设置的默认值改为私有哨兵对象not_set并立即实现未来行为。传入任何其他值会触发弃用警告但除此之外是 no-op仍然使用未来行为。对于这种做法会造成特别大破坏的设置还有一条两阶段过渡路径先发出警告并新增一个可传入的特殊值来选择加入opt-in未来行为到下一个 major 版本时再把该特殊值本身弃用、使其变成 no-op并让传入任何其他值成为错误。not_set哨兵的真实实现见 hypothesis/src/hypothesis/utils/conventions.py它由UniqueIdentifier工厂生成repr即字符串本身从而在日志与错误消息中清晰可读。settings.__init__中每个参数都以 not_set作为默认值hypothesis/src/hypothesis/_settings.py 中对每个参数判断是not_set就从父设置继承否则校验并采用新值——这就是改了默认值即切换未来行为这一弃用策略的落地机制。引擎变更Engine Changes触及核心时的双重要求引擎变更指任何改变 Hypothesis 工作方式基本原理的变更。经验法则只要碰到hypothesis.internal.conjecture下的文件就算Python 版本即 hypothesis/src/hypothesis/internal/conjecture/ 目录——其中包含engine.py、data.py、shrinker.py、pareto.py等核心模块。所有此类变更必须满足由DRMacIver 或 Zac-HD批准或由其本人创作。由不是 DRMacIver 的某人批准或创作——手册明确指出这一节代码存在严重问题太多东西只有 DRMacIver 真正理解团队想改变这种局面因此强制引入第二双眼睛。如果合适带一个 hypothesis/tests/quality/test_discovery_ability.py 中的测试展示以前难以发现的示例现在能被发现该文件用统计假设检验验证各策略生成的分布形态核心辅助函数define_test在文件头部。如果合适带一个 hypothesis/tests/quality/test_shrink_quality.py 中的测试展示对 shrinker 的改进例如test_integers_from_minimizes_leftwards验证minimal(integers(min_value101)) 101这类收缩质量断言。非阻塞问题Non-Blocking Questions以下问题不应阻塞合并但可能导致额外的 issue 或变更被打开由原作者或评审者发起本次变更是否被评审清单覆盖得很好清单中是否有值得补充的条目来改进指南本身评审这些条目时是否有令人困惑或恼火的体验它们能否被改进这次变更是否暗示了更一般性的改进这些改进是否有关联的 issue 和/或 PR这本质上是元评审手册鼓励评审者不仅评审代码也评审评审流程本身——这与文档开头我们仍在摸索这套流程的态度一脉相承。请求更多工作Asking for More Work克制 vs 合理的例外评审者一般不应请求超出 PR 原始目标的变更。这是整个工作流的核心设计哲学让正确变更变得便宜making correct changes should be cheap。如果改一处就必须连带改一堆相关区域变更的成本又会变高。当然这不包括为保证变更正确所必需的额外工作——例如改了公共功能就必然要更新其文档那不是 scope creep只是正常范围。如果 PR 暗示了额外工作评审者与作者之间应确保存在相关的跟踪 issue对应上文非阻塞问题第 3 条但双方都没有义务真的去做这些 issue 上的工作。默认由评审者来开这些 issue作者当然也欢迎。同时手册承认在某些情况下合理扩大 PR 范围是正当的不做会导致后续麻烦例如由于向后兼容要求可能值得要求加入一些以后几乎肯定会加的功能以便函数参数顺序更合理。新增功能若缺了某块就极度不完整判据是没有它这个功能几乎永远不会有用litmus testthis will almost never be useful because...。这仍然相当主观但只要存在至少一个该变更相比现状是明显改进的正当用例就说明不适用此例外。如果界限不清评审者可以自由地建议额外工作——但如果作者是新人务必说明这是建议而非要求作者同样可以自由地拒绝该建议。落地支撑RELEASE.rst与发布工具链如何强制这些规则上述检查清单中有多项直接围绕RELEASE.rst这个文件不仅是评审对象还被自动化工具严格解析。理解工具链能让你在评审时更精确地判断格式是否正确、版本号是否合理。格式与解析tooling/src/hypothesistooling/release.py 用正则^RELEASE_TYPE: (major|minor|patch)解析首行只接受三种发布类型首行会被从 changelog 中移除其余内容才是正文。当前仓库的 hypothesis/RELEASE.rst 就是一个patch实例。版本 bump 规则release.py 的 bump_version_info() 实现语义化版本递增major/minor/patch 对应递增不同位并将低位清零。这与手册changelog 应 bump minor 或 patch以及 documentation 手册中major 仅由核心团队在充分讨论后使用的约定一致。自动写入 changelogupdate_changelog_and_version() 会把RELEASE.rst内容格式化后插入 hypothesis/docs/changelog.rst 顶部并同步更新 Rust 侧的Cargo.toml版本与sinceRELEASEDAY占位日期——所以评审者看到源码里残留sinceRELEASEDAY是正常的发布时会自动替换。写作模板hypothesis/RELEASE-sample.rst 给出了标准模板首行RELEASE_TYPE:正文用 Sphinx 交叉引用:func:、:class:、:issue:、:pull:、:v:、:doc:并以Thanks to 名字 for this ...结尾首次贡献者别忘了把自己加进 AUTHORS.rst。CI 强制校验whole_repo_tests/whole_repo/test_release_files.py 会在有源码变更但没有RELEASE.rst时让测试失败并检查RELEASE.rst是否存在合并冲突残留、是否与已发布 changelog 重复。这意味着忘写 changelog无法偷偷通过 CI——评审者可以利用这一点把精力集中在内容质量而非格式提醒上。结语评审是维护质量的杠杆把这份手册与仓库源码对照起来看会发现 Hypothesis 的评审体系是一个闭环正交性规则约束 PR 粒度RELEASE.rst承载用户可见的描述发布工具链把描述自动转成 changelog 并 bump 版本CI 测试强制文件存在与格式合法而 API/设置/引擎的分场景清单则把用户生活与维护者生活这两个抽象目标翻译成可执行的具体检查。作为评审者你不需要记住每一条的原文——只要把握住两个核心问题会不会让用户变糟、会不会让维护者变糟再按本节清单逐项核对就能对 Hypothesis 的变更给出专业、可辩护的评审意见。评审之后别忘了顺手回答非阻塞问题里的元问题这份清单本身还有哪些可以改进毕竟手册自己说得很清楚Were still figuring this thing out!赞分享测试开发工具【免费下载链接】hypothesisThe property-based testing library for Python项目地址https://gitcode.com/gh_mirrors/hy/hypothesis点击查看免费下载相关推荐Apache MXNet 社区代码评审指南评审者检查清单与贡献者实战手册Apache MXNet 社区代码评审指南评审者检查清单与贡献者实战手册 Apache MXNet 是一个由社区驱动的开源深度学习框架其质量保障高度依赖一套深度学习人工智能机器学习分布式训练OpenMetadata PR 评审技能深度解析以维护者视角审查 Pull Request 的完整方法论OpenMetadata PR 评审技能深度解析以维护者视角审查 Pull Request 的完整方法论 导读 本文围绕 OpenMetadata 开源仓库中数据目录数据血缘数据治理后端MCP 服务Jekyll 维护者实战从评审标准到 CI 门禁的 Pull Request 审查全流程Jekyll 维护者实战从评审标准到 CI 门禁的 Pull Request 审查全流程 本文以 Jekyll 官方维护者指南 Reviewing a Pul前端CMS上一篇TikTok评论采集神器3步实现抖音评论数据自动化收集与分析下一篇Windows更新修复终极方案三招彻底解决系统更新问题创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表