貢獻入門

我們非常歡迎並感激您的貢獻。每一份幫助都很重要,請不要猶豫!

功能請求和反饋

喜歡 pytest 嗎?在 Twitter 上或在您的博客文章中分享一些愛意吧!

我們也很樂意聽取您的建議和提議。請隨時將它們作為問題提交,並

  • 詳細說明它們應該如何運作。

  • 將範圍保持盡可能狹窄。這將使實現更容易。

報告錯誤

問題追踪器中報告 pytest 的錯誤。

如果您正在報告錯誤,請包括

  • 您的操作系統名稱和版本。

  • 任何有助於故障排除的本地設置詳細信息,具體包括 Python 解釋器版本、已安裝的庫和 pytest 版本。

  • 重現錯誤的詳細步驟。

如果您能夠編寫一個目前失敗但應該通過的演示測試(xfail),那將是一個非常有用的提交,即使您無法修復錯誤本身。

修復錯誤

查看GitHub 上的錯誤問題。同樣查看對新貢獻者友好的“好的首次問題”問題

與開發人員交流,了解您如何修復特定的錯誤。為了表明您將處理特定問題,請在該特定問題上添加一條該效果的評論。

別忘了也要檢查您喜歡的插件的問題追踪器!

實現功能

查看GitHub 上的增強問題

與開發人員交流,了解您如何實現特定功能。

撰寫文檔

Pytest 總是需要更多的文檔。究竟需要什麼?

  • 更多補充文件。您可能發現有些地方不太清楚嗎?

  • 文件翻譯。我們目前只有英文版本。

  • 文檔字符串。永遠不能有太多。

  • 部落格文章、文章等 - 都非常受歡迎。

您也可以直接在 GitHub 網頁界面中編輯文檔文件,而無需使用本地副本。這對於小修復很方便。

注意

使用以下命令在本地構建文檔

$ 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 插件存儲庫,該存儲庫必須包含以下內容

  • 具有 pytest- 前綴名稱、版本號、作者、簡短和長描述的打包元數據。

  • 使用 tox 運行測試的 tox 配置

  • 一個描述如何使用插件以及在哪些平台上運行的 README

  • 包含著授權資訊的 LICENSE 檔案,並且其封裝的元數據中有相符的資訊。

  • 用於錯誤報告和增強請求的問題追蹤器。

  • 變更日誌

如果沒有貢獻者強烈反對且有兩人同意,該存儲庫可以轉移到 pytest-dev 組織。

以下是存儲庫轉移通常的進行方式(以名為 joedoe/pytest-xyz 的存儲庫為例)

  • joedoe 將存儲庫所有權轉移給 pytest-dev 管理員 calvin

  • calvin 建立 pytest-xyz-adminpytest-xyz-developers 團隊,並邀請 joedoe 作為維護者加入其中。

  • calvin 將存儲庫轉移到 pytest-dev 並配置團隊訪問權限

    • pytest-xyz-admin 管理員 權限;

    • pytest-xyz-developers 寫入 權限;

pytest-dev/Contributors 團隊對所有專案擁有寫入權限,每個專案管理員都屬於其中。我們建議每個插件至少有三個人具有對 PyPI 進行發布的權利。

存儲庫所有者可以放心,沒有任何 pytest-dev 管理員會對您的存儲庫進行發布或以任何方式擁有所有權,除非在多次聯繫嘗試幾個月後某人變得無法回應的極端情況下。如上所述,目標是分享維護並避免「插件被遺棄」。

準備拉取請求

簡短版本

  1. 分叉該存儲庫。

  2. 如果需要,從上游取得標籤(如果您僅克隆了主要的 git fetch --tags https://github.com/pytest-dev/pytest)。

  3. 啟用並安裝 pre-commit 以確保遵循樣式指南和程式碼檢查。

  4. 遵循 PEP-8 進行命名。

  5. 使用 tox 執行測試。

    tox -e linting,py39
    

    上述測試環境通常足以在本地涵蓋大多數情況。

  6. 撰寫一個 changelog 條目:changelog/2574.bugfix.rst,使用問題ID號碼和其中一個 featureimprovementbugfixdocdeprecationbreakingvendortrivial 作為問題類型。

  7. 除非您的更改是微不足道的或文檔修正(例如,小節錯別字或改寫)請按字母順序將自己添加到 AUTHORS 文件中。

詳細版本

什麼是“拉取請求”?它通知項目的核心開發人員您想要審查並合併的更改。 拉取請求存儲在 GitHub 伺服器 上。 一旦您發送了拉取請求,我們可以討論其潛在修改,甚至稍後添加更多提交。GitHub幫助中心有一個關於拉取請求工作原理的優秀教程。

這是一個簡單的概述,帶有 pytest 特定的部分

  1. 分叉 pytest GitHub 存儲庫。 將 pytest 作為分叉存儲庫名稱是可以的,因為它將存在您的用戶下。

  2. 使用 git 在本地克隆您的分支並創建一個分支

    $ 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”版本號,錯誤修復通常會在微版本中發布,而功能則會在次要版本中發布,不相容的更改則在主要版本中發布。

    您需要標籤來在本地進行測試,所以請確保您從主存儲庫中獲取了標籤。如果您懷疑您沒有,請將主存儲庫設置為上游並提取標籤

    $ git remote add upstream https://github.com/pytest-dev/pytest
    $ git fetch upstream --tags
    

    如果您需要一些關於Git的幫助,請參閱此快速入門指南: https://git.wiki.kernel.org/index.php/QuickStart

  3. 安裝 pre-commit 及其鉤子在 pytest 存儲庫上

    $ pip install --user pre-commit
    $ pre-commit install
    

    之後 pre-commit 每當您提交時都會運行。

    https://pre-commit.dev.org.tw/ 是一個管理和維護多語言pre-commit鉤子的框架,以確保代碼風格和代碼格式一致。

  4. 安裝 tox

    Tox 用於運行所有測試,並將自動設置虛擬環境以運行測試。 (將隱含使用 https://virtualenv.pypa.io/en/latest/)

    $ pip install tox
    
  5. 運行所有測試

    您需要在系統中有Python 3.8或更高版本可用。 現在運行測試就像發出這個命令一樣簡單

    $ tox -e linting,py39
    

    此命令將使用“tox”工具運行針對Python 3.9的測試,並執行“lint”代碼風格檢查。

  6. 您現在可以編輯本地工作副本並根據需要再次運行測試。 請遵循 PEP-8 的命名規範。

    您可以向 tox 傳遞不同的選項。 例如,要在Python 3.9上運行測試並向 pytest 傳遞選項 (例如在失敗時輸入pdb) ,您可以這樣做

    $ tox -e py39 -- --pdb
    

    或者只在Python 3.9中運行特定測試模塊的測試

    $ tox -e py39 -- testing/test_config.py
    

    提交時,如果需要,pre-commit 將重新格式化文件。

  7. 如果您不想使用 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
    
  8. changelog 中新增一個新的變更日誌項目。檔案應該命名為 <issueid>.<type>.rst,其中 issueid 是與該變更相關的問題編號,typefeatureimprovementbugfixdocdeprecationbreakingvendortrivial 中的一個。如果變更不影響 pytest 的文件化行為,則可以跳過創建變更日誌項目。

  9. 如果尚未在 AUTHORS 檔案中,請以字母順序將自己加入其中。

  10. 當您的測試通過且您對您的更改滿意時,請提交並推送更改。

    $ git commit -a -m "<commit message>"
    $ git push -u
    
  11. 最後,通過 GitHub 網站提交拉取請求,使用這些數據。

    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 中實現。如果有疑問,請打開拉取請求,並根據您的最佳猜測進行討論。

加入開發團隊

任何成功完成拉取請求並且不需要開發團隊進行任何額外工作的人,如果願意,都可以獲得提交訪問權限(如果我們忘記問,請友好地提醒)。這並不意味著您的貢獻流程有任何變化:每個人都需要經過相同的拉取請求和審查過程,除非已獲得批准,否則任何人都不會合併自己的拉取請求。但這意味著您可以更全面地參與開發過程,因為您可以在審查過後自行合併其他貢獻者的拉取請求。

為下一個補丁發布版進行錯誤修復的反向移植

Pytest 每隔幾週或幾個月發布一次特性版本。在此期間,將上一個特性版本進行補丁發布,僅包含錯誤修復。錯誤修復通常修復回歸問題,但也可能是應該在下一個特性版本發布之前傳達給用戶的任何更改。

例如,假設最新版本是1.2.3,您希望在1.2.4中包含一個錯誤修復(請查看https://github.com/pytest-dev/pytest/releases以獲取實際最新版本)。此操作步驟如下:

  1. 首先,確保該錯誤已在主分支上修復,並通過常規拉取請求進行提交,如上所述。唯一的例外是,如果該錯誤修復對主分支不再適用。

自動方法

為您想要回溯的PR添加一個backport 1.2.x標籤。這將創建一個針對1.2.x分支的回溯PR。

手動方法

  1. git checkout origin/1.2.x -b backport-XXXX # 在此處使用主要PR號碼

  2. 定位PR中的合併提交,在合併消息中,例如

    nicoddemus合併了提交0f8b462到pytest-dev:main

  3. git cherry-pick -x -m1 REVISION # 使用您在上面找到的修訂版(0f8b462

  4. 打開一個針對1.2.x的PR

    • 在消息中加上前綴[1.2.x]

    • 刪除PR正文,它通常包含重複的提交消息。

誰來進行回溯

如上所述,錯誤應首先在主分支上修復(除非在先前的發布中只有一個錯誤的情況下)。那麼,誰應該執行上述回溯程序呢?

  1. 如果該錯誤是由核心開發人員修復的,那麼由該核心開發人員負責執行回溯。

  2. 然而,通常合併是由其他維護人員執行的,如果他們有時間,他們也可以執行回溯程序,這樣做是很好的。

  3. 對於由非維護人員提交的錯誤,預期核心開發人員將執行回溯,通常是在main上合併了PR的那個人。

  4. 如果非維護人員注意到一個已在main上修復但尚未回溯的錯誤(因為維護人員忘記應用needs backport標籤,或者僅僅是遺漏了),歡迎他們打開一個帶有回溯的PR。該程序簡單且確實有助於項目的維護。

以上所有內容並非規則,僅僅是一些關於回溯(backports)應該預期的指南/建議。

處理搁置的問題/PR

搁置的問題/PR是指 pytest 的貢獻者提出問題/變更,而作者在相當長的時間內沒有回答/實現它們,或者討論因為人們似乎失去了興趣而中止。

人們不回答問題或實現請求變更的原因有很多:他們可能忙碌、失去興趣,或者只是忘記了,但事實是,在開源軟件中這是非常常見的。

pytest 團隊非常感激每一個問題和拉取請求,但由於每天都有許多問題和拉取請求被提交,我們嘗試通過定期關閉它們來減少搁置的問題和 PR 的數量。當以這種方式關閉一個問題/拉取請求時,這絕不是對問題/拉取請求所處理主題的拒絕,而僅僅是我們清理隊列並使維護人員的工作更加可管理的一種方式。提交者隨時都可以在自己的時間重新打開問題/拉取請求,如果有意義的話。

何時關閉

以下是維護人員在決定因為缺乏活動而關閉問題/PR時使用的一些一般規則

  • 標記為 questionneeds information 的問題:14 天未活動後關閉。

  • 標記為 proposal 的問題:6 個月未活動後關閉。

  • 拉取請求:一個月後,考慮通知作者,更新相關問題,或者考慮關閉。對於幾乎完成的拉取請求,團隊應該考慮完成並合併它。

以上都不是嚴格的規則,僅僅是指南,通常是會根據具體情況進行審查。

關閉拉取請求

關閉拉取請求時,需要承認提交者所展示的時間、努力和興趣。正如之前提到的,團隊並不打算完全拒絕一個停滯不前的拉取請求,而僅僅是為了清理我們的隊列,因此在關閉一個因為停滯不前而關閉的拉取請求時,應該發送如下消息

嗨 <contributor>,

首先,我們要感謝您在此工作上花費的時間和精力,pytest 團隊深表感謝。

但我們注意到您已經有一段時間沒有更新這個 PR 了。pytest 是一個高活躍的項目,每天都有許多問題/拉取請求被開啟,因此對我們維護人員來說很難跟踪哪些 PR 已經準備好合併、需要審查或需要更多關注。

因此,出於這些原因,我們認為現在最好關閉這個 PR,但這絕不意味著對您的變更的拒絕。我們仍然鼓勵您在準備好重新處理時重新打開此 PR(這只是一個按鈕的點擊)。

再次感謝您花時間處理此事,希望您稍後能回來處理!

<再見>

關閉問題

當提交拉取請求以修復問題時,請在 PR 描述和/或提交中添加像 closes #XYZW 這樣的文本(其中 XYZW 是問題號)。更多信息請參見GitHub文檔

當問題是由於用戶錯誤引起的(例如,對功能的誤解),請禮貌地向用戶解釋問題的真正原因並要求他們關閉該問題,如果他們沒有進一步的問題的話。如果原始請求者不作回應,則將按照上述 處理過期問題/PR 部分的描述處理該問題。