贡献入门¶
非常欢迎和感谢您的贡献。任何一点帮助都算数,所以不要犹豫!
功能请求和反馈¶
您喜欢 pytest 吗?在 Twitter 或您的博客文章中分享一些爱意!
我们也希望了解您的建议和意见。请随时将其作为问题提交,并
详细说明它们应如何工作。
尽可能缩小范围。这将使其更容易实现。
报告错误¶
在问题跟踪器中报告 pytest 的错误。
如果您要报告错误,请包括
您的操作系统名称和版本。
可能有助于解决问题的任何有关您本地设置的详细信息,特别是 Python 解释器版本、已安装的库和 pytest 版本。
重现错误的详细步骤。
如果您能编写一个当前失败但应该通过的演示测试(xfail),那也是一个非常有用的提交,即使您无法修复错误本身。
修复错误¶
查看GitHub 上的错误问题。另请参阅“好的第一个问题”问题,它们对新贡献者友好。
联系开发人员以了解如何修复特定错误。要表明您将处理某个特定问题,请在该特定问题上添加一条评论以表明这一点。
别忘了查看您最喜爱的插件的问题跟踪器!
实现功能¶
联系开发人员以了解如何实现特定功能。
编写文档¶
Pytest 始终可以使用更多文档。究竟需要什么?
更多补充文档。您是否发现某些内容不清楚?
文档翻译。我们目前只有英文。
文档字符串。它们永远不会太多。
博客文章、文章等——这些都非常受欢迎。
您还可以在 GitHub Web 界面中直接编辑文档文件,而无需使用本地副本。对于小修补程序,这很方便。
注意
使用以下命令在本地构建文档
$ tox -e docs
构建的文档应在 doc/en/_build/html
中,其中“en”是指文档语言。
Pytest 有一个 API 参考,它在很大程度上是从文档项的文档字符串中自动生成的。Pytest 使用Sphinx 文档字符串格式。例如
def my_function(arg: ArgType) -> Foo:
"""Do important stuff.
More detailed info here, in separate paragraphs from the subject line.
Use proper sentences -- start sentences with capital letters and end
with periods.
Can include annotated documentation:
:param short_arg: An argument which determines stuff.
:param long_arg:
A long explanation which spans multiple lines, overflows
like this.
:returns: The result.
:raises ValueError:
Detailed information when this can happen.
.. versionadded:: 6.0
Including types into the annotations above is not necessary when
type-hinting is being used (as in this example).
"""
向 pytest-dev 提交插件¶
核心、一些插件和支持代码的 Pytest 开发发生在 pytest-dev
组织下的存储库中
所有 pytest-dev 贡献者团队成员均对所有包含的存储库拥有写访问权限。Pytest 核心和插件通常使用 拉取请求 开发到各自的存储库中。
pytest-dev
组织的目标是
为流行的 pytest 插件提供一个中心位置
分担一些维护责任(如果某个维护者不再希望维护插件)
你可以通过订阅 pytest-dev 邮件列表 并写一封邮件指向你现有的 pytest 插件存储库来提交你的插件,该存储库必须具有以下内容
PyPI 存在,其中包含包装元数据,该元数据包含以
pytest-
为前缀的名称、版本号、作者、简短和详细说明。README
描述如何使用插件以及它在哪些平台上运行。LICENSE
文件包含许可信息,其包装元数据中的信息相匹配。用于错误报告和增强请求的问题跟踪器。
变更日志。
如果没有贡献者强烈反对,并且有两个人同意,则可以将存储库转移到 pytest-dev
组织。
以下是如何通常进行存储库转移的概述(使用名为 joedoe/pytest-xyz
的存储库作为示例)
joedoe
将存储库所有权转移给pytest-dev
管理员calvin
。calvin
创建pytest-xyz-admin
和pytest-xyz-developers
团队,邀请joedoe
作为维护者加入这两个团队。calvin
将存储库转移到pytest-dev
并配置团队访问权限pytest-xyz-admin
管理员访问权限;pytest-xyz-developers
写入访问权限;
pytest-dev/Contributors
团队对所有项目具有写访问权限,并且每个项目管理员都在其中。我们建议每个插件至少有三人有权发布到 PyPI。
存储库所有者可以放心,没有 pytest-dev
管理员会以任何方式发布你的存储库或获取所有权,除非在极少数情况下,在经过数月的联系尝试后,某人仍然没有响应。如前所述,目标是分担维护并避免“插件弃用”。
准备拉取请求¶
简短版本¶
Fork 存储库。
如有必要,从上游获取标签(如果你只克隆了主
git fetch --tags https://github.com/pytest-dev/pytest
)。启用并安装 pre-commit 以确保遵循风格指南和代码检查。
命名时遵循 PEP-8。
使用
tox
运行测试tox -e linting,py39
上述测试环境通常足以在本地涵盖大多数情况。
编写
changelog
条目:changelog/2574.bugfix.rst
,针对问题类型使用问题 ID 号码和feature
、improvement
、bugfix
、doc
、deprecation
、breaking
、vendor
或trivial
之一。除非你的更改是琐碎的或文档修复(例如,小部分内容的错别字或重新表述),请按字母顺序将自己添加到
AUTHORS
文件中。
长版本¶
什么是“pull request”?它会告知项目的核心开发者你希望审查和合并的更改。Pull request 存储在 GitHub 服务器 上。一旦你发送 pull request,我们就可以讨论其潜在修改,甚至稍后添加更多提交。在 GitHub 帮助中心 中有一个关于 Pull Request 在工作原理方面的出色教程。
下面是简单的概述,其中包含特定于 pytest 的部分
Fork pytest GitHub 存储库。使用
pytest
作为你的 fork 存储库名称是可以的,因为它将存在于你的用户下。使用 git 在本地克隆你的 fork 并创建一个分支
$ git clone [email protected]:YOUR_GITHUB_USERNAME/pytest.git $ cd pytest $ git fetch --tags https://github.com/pytest-dev/pytest # now, create your own branch off "main": $ git checkout -b your-bugfix-branch-name main
鉴于我们有“major.minor.micro”版本号,错误修复通常会在 micro 版本中发布,而功能将在次要版本中发布,不兼容的更改将在主要版本中发布。
你需要这些标记才能在本地进行测试,因此请确保你拥有来自主存储库的标记。如果你怀疑自己没有,请将主存储库设置为上游并获取标记
$ git remote add upstream https://github.com/pytest-dev/pytest $ git fetch upstream --tags
如果你需要一些 Git 方面的帮助,请遵循此快速入门指南:https://git.wiki.kernel.org/index.php/QuickStart
在 pytest 存储库上安装 pre-commit 及其钩子
$ pip install --user pre-commit $ pre-commit install
之后,每当你提交时,
pre-commit
都会运行。https://pre-commit.git.js.cn/ 是一个用于管理和维护多语言 pre-commit 钩子的框架,以确保代码样式和代码格式保持一致。
安装 tox
Tox 用于运行所有测试,并将自动设置虚拟环境以在其中运行测试。(将隐式使用 https://virtualenv.pypa.io/en/latest/)
$ pip install tox
运行所有测试
你的系统中需要有 Python 3.8 或更高版本。现在,运行测试就像发出此命令一样简单
$ tox -e linting,py39
此命令将通过“tox”工具针对 Python 3.9 运行测试,还将执行“lint”编码样式检查。
你现在可以编辑你的本地工作副本,并在必要时再次运行测试。请遵循 PEP-8 进行命名。
您可以向
tox
传递不同的选项。例如,要在 Python 3.9 上运行测试并将选项传递给 pytest(例如,在失败时进入 pdb),您可以执行$ tox -e py39 -- --pdb
或者仅在 Python 3.9 上运行特定测试模块中的测试
$ tox -e py39 -- testing/test_config.py
提交时,
pre-commit
会根据需要重新格式化文件。如果您不想使用
tox
而更喜欢直接运行测试,那么我们建议创建一个虚拟环境并使用带有dev
额外选项的可编辑安装$ python3 -m venv .venv $ source .venv/bin/activate # Linux $ .venv/Scripts/activate.bat # Windows $ pip install -e ".[dev]"
之后,您可以编辑文件并正常运行 pytest
$ pytest testing/test_config.py
在
changelog
中创建新的变更日志条目。该文件应命名为<issueid>.<type>.rst
,其中 issueid 是与更改相关的 issue 的编号,而 type 是feature
、improvement
、bugfix
、doc
、deprecation
、breaking
、vendor
或trivial
之一。如果您更改不会影响 pytest 的记录行为,则可以跳过创建变更日志条目。如果您尚未在
AUTHORS
文件中添加自己,请按字母顺序添加。在测试通过且您对更改感到满意后,提交并推送
$ git commit -a -m "<commit message>" $ git push -u
最后,使用此数据通过 GitHub 网站提交拉取请求
head-fork: YOUR_GITHUB_USERNAME/pytest compare: your-branch-name base-fork: pytest-dev/pytest base: main
编写测试¶
通常使用 pytester fixture 作为“黑盒”测试来编写插件或 pytest 自身的测试。
例如,要确保一个简单的测试通过,您可以编写
def test_true_assertion(pytester):
pytester.makepyfile(
"""
def test_foo():
assert True
"""
)
result = pytester.runpytest()
result.assert_outcomes(failed=0, passed=1)
或者,可以使用类似 glob 的表达式根据终端的实际输出进行检查
def test_true_assertion(pytester):
pytester.makepyfile(
"""
def test_foo():
assert False
"""
)
result = pytester.runpytest()
result.stdout.fnmatch_lines(["*assert False*", "*1 failed*"])
在选择编写新测试的文件时,请查看现有文件并查看是否有看起来很合适的文件。例如,关于 --lf
选项中 bug 的回归测试应进入 test_cacheprovider.py
,因为此选项是在 cacheprovider.py
中实现的。如果您有疑问,请继续使用您的最佳猜测打开 PR,我们可以在代码中讨论此事。
加入开发团队¶
任何成功完成拉取请求的人(该请求不需要开发团队额外工作即可合并)如果愿意,他们自己将获得提交访问权限(如果我们忘记询问,请发送友好的提醒)。这并不意味着您的贡献工作流程有任何变化:每个人都经历相同的拉取请求和审查流程,并且没有人合并自己的拉取请求,除非已经获得批准。然而,这确实意味着您可以更全面地参与开发过程,因为在审查其他贡献者的拉取请求后,您可以自己合并这些请求。
为下一个补丁版本回传 bug 修复¶
Pytest 每隔几周或几个月就会发布一个功能版本。在此期间,会对前一个功能版本进行补丁版本发布,其中仅包含 bug 修复。这些 bug 修复通常修复回归,但可能是任何在下一个功能版本发布之前应让用户了解的更改。
例如,假设最新版本是 1.2.3,您想在 1.2.4 中包含一个 bug 修复(请查看 https://github.com/pytest-dev/pytest/releases 了解实际的最新版本)。为此,程序如下
首先,请确保已在
main
分支中修复了 bug,并附有常规的拉取请求,如上所述。例外情况是,如果 bug 修复不再适用于main
。
自动方法
为要回溯的 PR 添加 backport 1.2.x
标签。这将在 1.2.x
分支上创建一个回溯 PR。
手动方法
git checkout origin/1.2.x -b backport-XXXX
# 在此处使用主 PR 编号在 PR 上找到合并提交,例如在 *已合并* 消息中
nicoddemus 将提交 0f8b462 合并到 pytest-dev:main
git cherry-pick -x -m1 REVISION
# 使用上面找到的修订版 (0f8b462
)。打开针对
1.2.x
的 PR使用
[1.2.x]
为消息添加前缀。删除 PR 正文,它通常包含重复的提交消息。
谁进行回溯¶
如上所述,错误应首先在 main
上修复(除了在极少数情况下,错误只发生在之前的版本中)。那么,谁应该执行上面描述的回溯程序?
如果错误是由核心开发人员修复的,那么由该核心开发人员负责进行回溯。
但是,合并通常是由其他维护人员完成的,在这种情况下,如果他们有时间,他们最好执行回溯程序。
对于非维护人员提交的错误,预计核心开发人员将进行回溯,通常是合并
main
上 PR 的人。如果非维护人员注意到
main
上已修复但尚未回溯的错误(由于维护人员忘记应用 *需要回溯* 标签,或只是错过了它),他们也可以打开一个包含回溯的 PR。此过程很简单,确实有助于项目的维护。
以上所有内容都不是规则,而只是关于我们应该对回溯有什么期望的一些准则/建议。
处理陈旧的问题/PR¶
陈旧的问题/PR 是指 pytest 贡献者要求提问/更改,但作者在相当长一段时间内还没有回答/实施它们,或者讨论只是因为人们似乎失去了兴趣而停止了。
人们不回答问题或不实施所要求的更改的原因有很多:他们可能很忙、失去兴趣或只是忘记了,但事实是这在开源软件中非常常见。
Pytest 团队非常感谢每位提交问题和请求的成员,但由于这是一个提交问题和请求量很大的项目,我们每天都会收到很多问题和请求,因此我们尝试通过定期关闭它们来减少陈旧的问题和请求的数量。当以这种方式关闭问题/请求时,这绝不是对问题/请求所涉及主题的驳回,而只是我们清理队列并使维护人员的工作更易于管理的一种方式。提交者始终可以在他们自己的时间内重新打开问题/请求,如果这样做有意义的话。
何时关闭¶
以下是维护人员在决定何时因缺乏活动而关闭问题/请求时使用的几个一般规则
标记为
question
或needs information
的问题:在 14 天不活动后关闭。标记为
proposal
的问题:在六个月不活动后关闭。请求:一个月后,考虑联系作者、更新链接的问题或考虑关闭。对于已接近完成的请求,团队应考虑完成并合并它。
以上不是硬性规则,而仅仅是指南,并且可以(而且经常会!)根据具体情况进行审查。
关闭请求¶
在关闭请求时,需要确认提交该请求的人所展示的时间、精力和兴趣。如前所述,团队无意完全驳回一个停滞的请求,而只是为了清理我们的队列,因此在关闭一个已过时的请求时,需要像下面这样的消息
嗨,
首先,我们要感谢您在处理此事上花费的时间和精力,pytest 团队对此深表感谢。
然而,我们注意到您已经有一段时间没有更新此请求。pytest 是一个高活动项目,每天都会打开许多问题/请求,因此我们维护人员很难跟踪哪些请求已准备好合并、需要审查或需要更多关注。
因此,出于这些原因,我们认为现在最好关闭此请求,但唯一目的是清理我们的队列,这绝不是对您更改的拒绝。我们仍然鼓励您在准备重新处理此请求时重新打开此请求(只需单击一下按钮即可)。
再次感谢您在处理此事上花费的时间,并希望您稍后能重新处理此事!
<bye>
关闭问题¶
当提交请求以修复问题时,请在请求说明和/或提交中添加类似 closes #XYZW
的文本(其中 XYZW
是问题编号)。有关更多信息,请参阅 GitHub 文档。
当问题是由于用户错误(例如对功能的误解)时,请礼貌地向用户解释提出的问题实际上不是问题,并要求他们在没有进一步问题的情况下关闭问题。如果原始请求者没有响应,则将按照上面 处理陈旧问题/请求 部分中所述处理问题。