貢獻¶
我們非常歡迎並感謝您的貢獻。 每一點幫助都很重要,所以請不要猶豫!
功能請求和回饋¶
您喜歡 pytest 嗎? 在 Twitter 或您的部落格文章中分享您的喜愛!
我們也想聽取您的建議和提議。 請隨時以 issue (問題) 形式提交它們,並
詳細說明它們應該如何運作。
盡可能保持範圍狹窄。 這將使其更容易實作。
報告錯誤¶
在 issue (問題) 追蹤器中報告 pytest 的錯誤。
如果您要報告錯誤,請包含
您的作業系統名稱和版本。
有關您本機設定的任何詳細資訊,可能有助於疑難排解,特別是 Python 解釋器版本、已安裝的函式庫和 pytest 版本。
重現錯誤的詳細步驟。
如果您可以編寫一個目前失敗但應該通過的示範測試 (xfail),這也是一個非常有用的提交,即使您無法自行修復錯誤。
修復錯誤¶
瀏覽 GitHub issues (問題) 中的錯誤。另請參閱 “good first issue” 問題,這些問題對新貢獻者很友善。
與開發人員交談,以了解如何修復特定錯誤。 若要表明您將處理特定問題,請在該特定 issue (問題) 上新增評論以表明意願。
別忘了也檢查您最喜歡的外掛程式的 issue (問題) 追蹤器!
實作功能¶
與開發人員交談,以了解如何實作特定功能。
撰寫文件¶
Pytest 始終可以有更多文件。 到底需要什麼?
更多補充文件。 您是否發現有任何不清楚的地方?
文件翻譯。 我們目前只有英文文件。
Docstrings (文件字串)。 永遠不嫌多。
部落格文章、文章等 – 都非常感謝。
您也可以直接在 GitHub 網頁介面中編輯文件檔案,而無需使用本機副本。 這對於小的修復可能很方便。
注意
使用以下命令在本機建置文件
$ tox -e docs
建置的文件應位於 doc/en/_build/html
中,其中 'en' 指的是文件語言。
Pytest 有一個 API 參考,其中大部分是從文件項目的 docstrings (文件字串) 自動產生。 Pytest 使用Sphinx docstring (文件字串) 格式。 例如
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 Contributors 團隊成員都擁有對所有包含儲存庫的寫入權限。 Pytest 核心和外掛程式通常使用pull requests (提取請求) 開發到各自的儲存庫。
pytest-dev
組織的目標是
為流行的 pytest 外掛程式提供中心位置
分擔一些維護責任 (以防維護者不再希望維護外掛程式)
您可以透過訂閱 pytest-dev 郵件列表並撰寫一封郵件指向您現有的 pytest 外掛程式儲存庫來提交您的外掛程式,該儲存庫必須具有以下內容
PyPI 存在,其中包含包裝 metadata (元資料),其中包含
pytest-
前綴名稱、版本號碼、作者、簡短和詳細描述。README
,描述如何使用外掛程式以及它在哪些平台上運行。LICENSE
檔案,其中包含許可資訊,並在包裝 metadata (元資料) 中包含匹配資訊。用於錯誤報告和增強請求的 issue (問題) 追蹤器。
變更日誌。
如果沒有貢獻者強烈反對且有兩人同意,則可以將儲存庫轉移到 pytest-dev
組織。
以下是儲存庫轉移通常如何進行的概要 (使用名為 joedoe/pytest-xyz
的儲存庫作為範例)
joedoe
將儲存庫所有權轉移給pytest-dev
管理員calvin
。calvin
建立pytest-xyz-admin
和pytest-xyz-developers
團隊,邀請joedoe
加入這兩個團隊作為維護者。calvin
將儲存庫轉移到pytest-dev
並配置團隊訪問權限pytest-xyz-admin
admin (管理員) 訪問權限;pytest-xyz-developers
write (寫入) 訪問權限;
pytest-dev/Contributors
團隊擁有對所有專案的寫入權限,並且每個專案管理員都在其中。 我們建議每個外掛程式至少有三個人有權發佈到 PyPI。
儲存庫所有者可以放心,沒有任何 pytest-dev
管理員會發佈您的儲存庫或以任何方式取得所有權,除非在極少數情況下,有人在數月的聯絡嘗試後變得沒有回應。 如所述,目標是分擔維護並避免「外掛程式棄置」。
準備 Pull Requests (提取請求)¶
簡短版本¶
Fork (分支) 儲存庫。
如有必要,從上游獲取標籤 (如果您僅 clone (克隆) main,則
git fetch --tags https://github.com/pytest-dev/pytest
)。啟用並安裝 pre-commit 以確保遵循樣式指南和程式碼檢查。
命名請遵循 PEP-8。
測試使用
tox
運行tox -e linting,py39
上面的測試環境通常足以涵蓋大多數本機情況。
撰寫
changelog
條目:changelog/2574.bugfix.rst
,使用 issue (問題) ID 號碼以及feature
、improvement
、bugfix
、doc
、deprecation
、breaking
、vendor
或trivial
其中之一作為 issue (問題) 類型。除非您的變更是 trivial (微不足道) 或文件修復 (例如,錯字或少量章節的重新措辭),否則請將您自己新增到
AUTHORS
檔案中,按字母順序排列。
完整版本¶
什麼是 “pull request (提取請求)”? 它會通知專案的核心開發人員您想要審查和合併的變更。 Pull requests (提取請求) 儲存在 GitHub 伺服器上。 一旦您發送 pull request (提取請求),我們就可以討論其潛在的修改,甚至稍後在其中新增更多 commits (提交)。 在 GitHub 幫助中心中,有一個關於 Pull Requests (提取請求) 如何運作的絕佳教學。
以下是一個簡單的概述,其中包含 pytest 特定的部分
Fork (分支) pytest GitHub 儲存庫。 使用
pytest
作為您的 fork (分支) 儲存庫名稱是可以的,因為它將位於您的使用者下。使用 git 在本機 clone (克隆) 您的 fork (分支),並建立一個 branch (分支)
$ git clone git@github.com: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 版本中發佈,而功能將在 minor 版本中發佈,不相容的變更則在 major 版本中發佈。
您將需要標籤在本機進行測試,因此請確保您擁有來自主要儲存庫的標籤。 如果您懷疑您沒有,請將主要儲存庫設定為 upstream (上游) 並獲取標籤
$ 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 及其 hook (鉤子)
$ pip install --user pre-commit $ pre-commit install
之後,每當您 commit (提交) 時,
pre-commit
都會運行。https://pre-commit.dev.org.tw/ 是一個用於管理和維護多語言 pre-commit hooks (預提交鉤子) 的框架,以確保程式碼樣式和程式碼格式一致。
安裝 tox
Tox 用於運行所有測試,並將自動設定 virtualenvs (虛擬環境) 以在其中運行測試。 (將隱式使用 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) 給 pytest,您可以執行$ tox -e py39 -- --pdb
或者僅在 Python 3.9 上在特定測試模組中運行測試
$ tox -e py39 -- testing/test_config.py
Commit (提交) 時,
pre-commit
將在必要時重新格式化檔案。如果您不想使用
tox
而是喜歡直接運行測試,那麼我們建議建立一個虛擬環境,並使用帶有dev
extra (額外) 功能的可編輯安裝$ 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
檔案中,請按字母順序新增。一旦您的測試通過並且您對您的變更感到滿意,請 Commit (提交) 並 push (推送)
$ git commit -a -m "<commit message>" $ git push -u
最後,使用此資料透過 GitHub 網站提交 pull request (提取請求)
head-fork: YOUR_GITHUB_USERNAME/pytest compare: your-branch-name base-fork: pytest-dev/pytest base: main
撰寫測試¶
為外掛程式或 pytest 本身撰寫測試通常使用 pytester fixture (夾具) 作為 “黑箱” 測試來完成。
例如,為了確保簡單的測試通過,您可以撰寫
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
選項中錯誤的回歸測試應放入 test_cacheprovider.py
中,因為此選項是在 cacheprovider.py
中實作的。 如果有疑問,請繼續開啟一個包含您最佳猜測的 PR,我們可以透過程式碼討論這個問題。
加入開發團隊¶
任何成功完成 pull request (提取請求) 的人,如果他們願意 (如果我們忘記詢問,請發送友善的提醒),將獲得 commit (提交) 權限,而無需開發團隊進行任何額外工作即可合併。 這並不意味著您的貢獻工作流程有任何改變:每個人都經歷相同的 pull-request (提取請求) 和審查流程,除非已獲得批准,否則沒有人合併自己的 pull requests (提取請求)。 然而,這確實意味著您可以更充分地參與開發流程,因為在審查其他貢獻者的 pull requests (提取請求) 後,您可以自行合併它們。
合併/壓縮指南¶
當 PR 獲得批准並準備好整合到 main
branch (分支) 時,您可以選擇merge (合併) commits (提交) 而不變更,或 squash (壓縮) 所有 commits (提交) 為單個 commit (提交)。
以下是一些關於如何進行的指南,基於單個 PR commit (提交) 歷史的範例
雜項 commits (提交)
實作 X
修復 test_a
將 myself 新增到 AUTHORS
fixup! 修復 test_a
更新 tests/test_integration.py
將 origin/main 合併到 PR branch (分支)
更新 tests/test_integration.py
在這種情況下,最好使用 Squash (壓縮) 合併策略:commit (提交) 歷史有點混亂 (並非貶義,通常只是 commit (提交) 變更,因為他們知道變更最終會被壓縮在一起),因此將所有內容壓縮為單個 commit (提交) 是最佳選擇。 您必須清理 commit (提交) 訊息,確保其包含有用的詳細資訊。
與同一主題相關的獨立 commits (提交)
實作 X
將 myself 新增到 AUTHORS
更新 CHANGELOG for X
在這種情況下,最好使用 Squash (壓縮) 合併策略:雖然 commit (提交) 歷史不像上面的範例那樣 “混亂”,但單個 commits (提交) 整體而言並沒有帶來太多價值,特別是當查看幾個月/幾年後的變更時。
獨立 commits (提交),每個都有自己的主題 (重構、重新命名等),但仍然有一個更大的主題/目的。
重構 class (類別) X 以準備 feature (功能) Y
移除 未使用的 方法
實作 feature (功能) Y
在這種情況下,最好使用 Merge (合併) 策略:每個 commit (提交) 本身都很有價值,即使它們整體上服務於一個共同的主題。 稍後查看歷史記錄時,最好將移除未使用的方法單獨放在其自己的 commit (提交) 中,以及更多資訊 (例如,它最初是如何變得未使用的)。
獨立 commits (提交),每個都有自己的主題,但除了改進程式碼庫 (使用更現代的技術、改進類型標註、移除雜亂等) 之外,沒有更大的主題/目的。
改進 X 中的內部名稱
將 type (類型) annotations (註釋) 新增到 Y
移除 不必要的 dict (字典) 訪問
移除 由於 EOL Python 而導致的無法訪問的 程式碼
在這種情況下,最好使用 Merge (合併) 策略:每個 commit (提交) 本身都很有價值,並且每個 commit (提交) 上的資訊從長遠來看都很有價值。
如前所述,這些是總體指南,而不是一成不變的規則。 此主題在 #12633 中進行了討論。
Backport PRs (反向移植 PR) (如那些從 backport
標籤自動建立的 PR) 應始終 squashed (壓縮),因為它們保留了原始 PR 作者。
為下一個修補程式版本反向移植錯誤修復¶
Pytest 每隔幾週或幾個月發佈一個功能版本。 在此期間,會對先前的功能版本進行修補程式發佈,僅包含錯誤修復。 錯誤修復通常修復回歸錯誤,但也可能是任何應在下一個功能版本之前到達使用者的變更。
例如,假設最新版本是 1.2.3,並且您想在 1.2.4 中包含錯誤修復 (查看 https://github.com/pytest-dev/pytest/releases 以獲取實際最新版本)。 此程序的步驟如下
首先,確保錯誤已在
main
branch (分支) 中修復,並使用常規 pull request (提取請求),如上所述。 如果錯誤修復不再適用於main
,則為例外情況。
自動方法
將 backport 1.2.x
標籤新增到您要反向移植的 PR。 這將針對 1.2.x
branch (分支) 建立反向移植 PR。
手動方法
git checkout origin/1.2.x -b backport-XXXX
# 在此處使用主要的 PR 號碼在 merged (已合併) 訊息中找到 PR 上的合併 commit (提交),例如
nicoddemus merged commit 0f8b462 into pytest-dev:main
git cherry-pick -x -m1 REVISION
# 使用您在上面找到的 revision (修訂版本) (0f8b462
)。開啟以
1.2.x
為目標的 PR在訊息中加上
[1.2.x]
前綴。刪除 PR body (內文),它通常包含重複的 commit (提交) 訊息。
誰進行反向移植¶
如上所述,錯誤應首先在 main
上修復 (除非在極少數情況下,錯誤僅發生在先前的版本中)。 那麼,誰應該執行上述反向移植程序?
如果錯誤是由核心開發人員修復的,則該核心開發人員主要負責進行反向移植。
但是,通常合併是由另一位維護人員完成的,在這種情況下,如果他們有時間,最好由他們執行反向移植程序。
對於非維護人員提交的錯誤,預計核心開發人員將執行反向移植,通常是合併
main
上 PR 的人員。如果非維護人員注意到
main
上已修復但尚未反向移植的錯誤 (由於維護人員忘記應用 needs backport 標籤,或只是純粹遺漏),他們也歡迎開啟包含反向移植的 PR。 此程序很簡單,確實有助於專案的維護。
以上所有內容都不是規則,而僅僅是一些關於我們應該對反向移植有何期望的指南/建議。
反向移植應 squashed (壓縮) (而不是 merged (合併)),因為這樣做可以正確保留原始 PR 作者。
處理過時的 issues (問題)/PRs (提取請求)¶
過時的 issues (問題)/PRs (提取請求) 是指 pytest 貢獻者已要求提出問題/變更,但作者在相當長的時間後仍未回答/實作它們,或者討論只是因為人們似乎失去興趣而停止。
人們不回答問題或實作請求的變更有很多原因:他們可能變得忙碌、失去興趣或只是忘記了,但事實是,這在開放原始碼軟體中非常常見。
pytest 團隊非常感謝每個 issue (問題) 和 pull request (提取請求),但由於這是一個高流量專案,每天提交許多 issues (問題) 和 pull requests (提取請求),我們嘗試透過定期關閉它們來減少過時的 issues (問題) 和 PRs (提取請求) 的數量。 當以這種方式關閉 issue (問題)/pull request (提取請求) 時,絕不表示拒絕 issue (問題)/pull request (提取請求) 所處理的主題,而只是一種讓我們清理佇列並使維護人員的工作更易於管理的方式。 提交者始終可以在稍後在自己的時間重新開啟 issue (問題)/pull request (提取請求),如果這是有意義的。
何時關閉¶
以下是維護人員在決定何時因缺乏活動而關閉 issues (問題)/PRs (提取請求) 時使用的一些一般規則
標記為
question
或needs information
的 issues (問題):在閒置 14 天後關閉。標記為
proposal
的 issues (問題):在閒置六個月後關閉。Pull requests (提取請求):一個月後,考慮 ping (提醒) 作者、更新連結的 issue (問題),或考慮關閉。 對於幾乎完成的 pull requests (提取請求),團隊應考慮完成並合併它。
以上 不是硬性規定,而僅僅是 指南,並且可以 (而且經常!) 在個案基礎上進行審查。
關閉 pull requests (提取請求)¶
關閉 Pull Request (提取請求) 時,需要確認提交它的人所展現的時間、精力和興趣。 如前所述,團隊的意圖不是完全駁回停滯的 pull request (提取請求),而僅僅是清理我們的佇列,因此當關閉過時的 pull request (提取請求) 時,類似於以下訊息是有道理的
嗨 <貢獻者>,
首先,我們要感謝您花費時間和精力處理這個問題,pytest 團隊深表感謝。
但是,我們注意到您已經有一段時間沒有更新此 PR 了。 pytest 是一個高活動專案,每天都有許多 issues (問題)/PRs (提取請求) 開啟,因此我們維護人員很難追蹤哪些 PR 準備好合併、審查或需要更多關注。
因此,由於這些原因,我們認為最好暫時關閉 PR,但唯一的目的是清理我們的佇列,這絕不是拒絕您的變更。 我們仍然鼓勵您在準備好重新開始時重新開啟此 PR (只需點擊一下按鈕即可)。
再次感謝您花時間處理這個問題,並希望您稍後可能會重新開始!
<再見>
關閉 issues (問題)¶
當提交 pull request (提取請求) 以修復 issue (問題) 時,請將類似 closes #XYZW
的文字新增到 PR 描述和/或 commits (提交) 中 (其中 XYZW
是 issue (問題) 號碼)。 有關更多資訊,請參閱 GitHub 文件。
當 issue (問題) 是由於使用者錯誤 (例如,誤解了某項功能) 時,請禮貌地向使用者解釋為什麼提出的 issue (問題) 實際上不是問題,並要求他們在沒有其他問題時關閉 issue (問題)。 如果原始請求者沒有回應,則 issue (問題) 將按照上面的 處理過時的 issues (問題)/PRs (提取請求) 章節中的描述進行處理。