已棄用和已移除功能

此頁面列出所有目前已棄用或在過去主要版本中已移除的 pytest 功能。目的是讓使用者清楚了解特定功能被移除的原因,以及應改用哪些替代方案。

已棄用的功能

以下是所有被視為已棄用的 pytest 功能的完整清單。使用這些功能會發出 PytestWarning 或其子類別,可以使用 標準警告篩選器 來過濾。

pytest.importorskip 關於 ImportError 的預設行為

自版本 8.2 起已棄用。

傳統上 pytest.importorskip() 會擷取 ImportError,其原始用意是略過未安裝相依模組的測試,例如使用不同的相依模組進行測試。

然而,某些套件可能會安裝在系統中,但由於其他問題而無法匯入,例如編譯錯誤或安裝中斷。在這些情況下,pytest.importorskip() 仍會靜默略過測試,但通常使用者希望看到意外錯誤,以便修復潛在問題。

8.2 中,exc_type 參數已被新增,讓使用者有能力傳遞 ModuleNotFoundError,以僅在無法真正找到模組時才略過測試,而不是因為其他錯誤。

預設僅捕捉 ModuleNotFoundError(並讓其他錯誤傳播)將會是最佳解,然而為了向後相容,pytest 將會保留現有行為,但在下列情況下會提出警告:

  1. 捕捉到的例外為 ImportError 類型,且

  2. 使用者沒有明確傳遞 exc_type

如果匯入嘗試引發 ModuleNotFoundError(通常情況),則模組會被略過且不會發出警告。

透過這種方式,通常情況將會持續以相同方式運作,而意外錯誤現在會發出警告,使用者可以透過明確傳遞 exc_type=ImportError 來壓制警告。

9.0 中,警告將會轉為錯誤,而在 9.1 中,pytest.importorskip() 預設將僅捕捉 ModuleNotFoundError,且不再發出任何警告 – 但使用者仍可以透過傳遞給 exc_type 來捕捉 ImportError

fspath 參數用於節點建構函式,已替換為 pathlib.Path

自版本 7.0 起已標示為已棄用。

為了支援從 py.path.local 轉換到 pathlibNode 建構函式(例如 pytest.Function.from_parent()pytest.Class.from_parent())的 fspath 參數現已棄用。

建構節點的外掛程式應傳遞 path 參數(類型為 pathlib.Path),而不是 fspath 參數。

建議實作自訂項目和收集器的外掛程式將 fspath 參數 (py.path.local) 取代為 path 參數 (pathlib.Path),並盡可能捨棄其他使用 py 函式庫的用法。

如果可能,具有自訂項目的外掛程式應使用 合作建構函式,以避免硬編碼僅傳遞給超類別的參數。

注意

Node 參數和屬性的名稱(新屬性為 path)與勾子(如下所述,舊參數為 path)的情況相反

這是由於歷史原因而產生的不幸結果,隨著我們逐漸擺脫 py 相依性,應該會在未來版本中解決(有關更詳細的討論,請參閱 問題 #9283)。

由於 reportinfo() 等方法正在進行遷移,預計仍會傳回 py.path.local 物件,因此節點仍同時具有 fspath (py.path.local) 和 path (pathlib.Path) 屬性,無論建構函式中使用哪個參數。我們預計會在未來的版本中棄用 fspath 屬性。

使用標記設定掛鉤規範/實作

在 pluggy(pytest 的外掛程式庫)成為其自己的套件並擁有明確的 API 之前,pytest 僅使用 pytest.mark 來設定掛鉤。

裝飾器 pytest.hookimpl()pytest.hookspec() 已推出多年,應改用這些裝飾器。

@pytest.mark.tryfirst
def pytest_runtest_call(): ...


# or
def pytest_runtest_call(): ...


pytest_runtest_call.tryfirst = True

應變更為

@pytest.hookimpl(tryfirst=True)
def pytest_runtest_call(): ...

已變更 hookimpl 屬性

  • tryfirst

  • trylast

  • optionalhook

  • hookwrapper

已變更 hookwrapper 屬性

  • firstresult

  • historic

py.path.local 已由 pathlib.Path 取代,用於掛鉤的參數

自版本 7.0 起已標示為已棄用。

為了支援從 py.path.local 轉換至 pathlib,下列掛鉤現在會接收額外的參數

隨附的 py.path.local 路徑已標示為不建議使用:手動呼叫這些掛鉤的外掛程式應只傳遞新的 pathlib.Path 參數,而使用者應變更其掛鉤實作以使用新的 pathlib.Path 參數。

注意

Node 參數和屬性的名稱,上述概述(新的屬性為 path hook 的情況相反(舊的參數為 path)。

這是由於歷史原因而產生的不幸結果,隨著我們逐漸擺脫 py 相依性,應該會在未來版本中解決(有關更詳細的討論,請參閱 問題 #9283)。

直接建構內部類別

自版本 7.0 起已標示為已棄用。

現在不建議直接建構下列類別

  • _pytest.mark.structures.Mark

  • _pytest.mark.structures.MarkDecorator

  • _pytest.mark.structures.MarkGenerator

  • _pytest.python.Metafunc

  • _pytest.runner.CallInfo

  • _pytest._code.ExceptionInfo

  • _pytest.config.argparsing.Parser

  • _pytest.config.argparsing.OptionGroup

  • _pytest.pytester.HookRecorder

這些建構函式一直被視為私有的,但現在會發出不建議使用的警告,這可能會在 pytest 8 中變成硬性錯誤。

pytest.Collectorpytest.Item 之間的菱形繼承

自版本 7.0 起已標示為已棄用。

定義一個自訂的 pytest 節點類型,同時是 ItemCollector(例如 File),現在會發出警告。它從未獲得明智的支持,而且會觸發難以除錯的錯誤。

提供 linting/程式碼分析的一些外掛程式已將此用作一種技巧。相反地,應該使用一個獨立的收集器節點,來收集項目。請參閱 使用非 Python 測試 以取得範例,以及 修正繼承的範例公關

自訂 Node 子類別的建構函式應採用 **kwargs

自版本 7.0 起已標示為已棄用。

如果 pytest.Item 等節點的自訂子類別覆寫 __init__ 方法,則它們應採用 **kwargs。因此,

class CustomItem(pytest.Item):
    def __init__(self, name, parent, additional_arg):
        super().__init__(name, parent)
        self.additional_arg = additional_arg

應轉換為

class CustomItem(pytest.Item):
    def __init__(self, *, additional_arg, **kwargs):
        super().__init__(**kwargs)
        self.additional_arg = additional_arg

以避免對 pytest 可傳遞至超類別的引數進行硬編碼。請參閱 使用非 Python 測試 以取得完整範例。

對於沒有衝突的情況,不會發出不建議使用的警告。對於有衝突的情況(例如 pytest.File 現在採用 path,而非 fspath,如 上述所述),現在會提出不建議使用的警告。

將標記套用至固定裝置函式

自版本 7.4 起不建議使用。

將標記套用至固定裝置函式從未產生任何效果,但這是一個常見的使用者錯誤。

@pytest.mark.usefixtures("clean_database")
@pytest.fixture
def user() -> User: ...

在這種情況下,使用者預期 usefixtures 標記會產生預期的效果,即在呼叫 user 時使用 clean_database 固定裝置,但實際上它根本沒有任何效果。

現在,當 pytest 遇到此問題時,它會發出警告,並會在未來版本中引發錯誤。

在測試函式中傳回非 None 值

自版本 7.2 起不建議使用。

如果測試函式傳回 None 以外的項目,現在會發出 pytest.PytestReturnNotNoneWarning

這可防止初學者常見的錯誤,例如他們預期傳回 bool 會導致測試通過或失敗

@pytest.mark.parametrize(
    ["a", "b", "result"],
    [
        [1, 2, 5],
        [2, 3, 8],
        [5, 3, 18],
    ],
)
def test_foo(a, b, result):
    return foo(a, b) == result

假設 pytest 忽略回傳值,這可能會令人驚訝,因為它永遠不會失敗。

適當的修正方式是將 return 變更為 assert

@pytest.mark.parametrize(
    ["a", "b", "result"],
    [
        [1, 2, 5],
        [2, 3, 8],
        [5, 3, 18],
    ],
)
def test_foo(a, b, result):
    assert foo(a, b) == result

函數/裝飾器 yield_fixture

自版本 6.2 起已棄用。

pytest.yield_fixturepytest.fixture() 的已棄用別名。

它已經存在很長一段時間了,因此可以安全地搜尋/替換。

已移除功能和重大變更

如我們的 後向相容性政策 政策所述,已棄用的功能只會在適當的棄用期間過後,在主要版本中移除。

一些無法棄用的重大變更也列在這裡。

支援為 nose 編寫的測試

自版本 7.2 起不建議使用。

已在版本 8.0 中移除。

支援執行為 nose 編寫的測試現已棄用。

nose 已處於維護模式多年,而且維護外掛程式並不容易,因為它會溢位到程式碼庫(請參閱 問題 #9886 以取得更多詳細資訊)。

設定/清除

可能會讓使用者感到驚訝的一件事是,純粹的 setupteardown 方法並非 pytest 原生,它們實際上是 nose 支援的一部分。

class Test:
    def setup(self):
        self.resource = make_resource()

    def teardown(self):
        self.resource.close()

    def test_foo(self): ...

    def test_bar(self): ...

原生 pytest 支援使用 setup_methodteardown_method(請參閱 方法和函式層級設定/清除),因此上述內容應變更為

class Test:
    def setup_method(self):
        self.resource = make_resource()

    def teardown_method(self):
        self.resource.close()

    def test_foo(self): ...

    def test_bar(self): ...

在整個程式碼庫中執行簡單的尋找/取代,即可輕鬆執行此操作。

@with_setup

使用 @with_setup 的程式碼,例如

from nose.tools import with_setup


def setup_some_resource(): ...


def teardown_some_resource(): ...


@with_setup(setup_some_resource, teardown_some_resource)
def test_foo(): ...

也需要移植到受支援的 pytest 樣式。執行此操作的方法之一是使用固定裝置

import pytest


def setup_some_resource(): ...


def teardown_some_resource(): ...


@pytest.fixture
def some_resource():
    setup_some_resource()
    yield
    teardown_some_resource()


def test_foo(some_resource): ...

屬性 compat_co_firstlineno

Nose 會檢查函式物件上的此屬性,以允許覆寫函式的推論行號。Pytest 不再尊重此屬性。

傳遞 msg=pytest.skippytest.failpytest.exit

自版本 7.0 起已標示為已棄用。

已在版本 8.0 中移除。

傳遞關鍵字引數 msgpytest.skip()pytest.fail()pytest.exit() 現已不建議使用,而應改用 reason。此變更旨在讓這些函式與 @pytest.mark.skip@pytest.mark.xfail 標記保持一致性,這些標記已接受 reason 引數。

def test_fail_example():
    # old
    pytest.fail(msg="foo")
    # new
    pytest.fail(reason="bar")


def test_skip_example():
    # old
    pytest.skip(msg="foo")
    # new
    pytest.skip(reason="bar")


def test_exit_example():
    # old
    pytest.exit(msg="foo")
    # new
    pytest.exit(reason="bar")

收集器 pytest.Instance

已在版本 7.0 中移除。

已移除 pytest.Instance 蒐集器類型。

先前,Python 測試方法會以 Class -> Instance -> Function 的方式蒐集。現在 Class 會直接蒐集測試方法。

大多數參照 Instance 的外掛程式會這麼做,目的是為了忽略或跳過它,使用像 if isinstance(node, Instance): return 這樣的檢查。此類外掛程式應在 pytest>=7 中移除對 Instance 的考量。不過,為了讓此類用法持續運作,已在 pytest.Instance_pytest.python.Instance 中實例化一個虛擬類型,而匯入它會發出不建議使用的警告。這已在 pytest 8 中移除。

使用 pytest.warns(None)

自版本 7.0 起已標示為已棄用。

已在版本 8.0 中移除。

pytest.warns(None) 現在已不建議使用,因為它經常被誤用。其正確用法是檢查程式碼是否發出任何類型的警告,例如 pytest.warns()pytest.warns(Warning)

請參閱 測試中警告的其他使用案例 以取得範例。

Parser.addoption 中向後相容

自版本 2.4 起已不建議使用。

已在版本 8.0 中移除。

在 pytest 8 中,已移除 Parser.addoption 的多種行為(自 pytest 2.4.0 起已不建議使用)

  • parser.addoption(..., help=".. %default ..") - 改用 %(default)s

  • parser.addoption(..., type="int/string/float/complex") - 改用 type=int 等。

命令列選項 --strict

自版本 6.2 起已棄用。

已在版本 8.0 中移除。

命令列選項 --strict 已棄用,建議改用 --strict-markers,它能更清楚地傳達此選項的功能。

我們計畫在未來重新引入 --strict,並將其設為所有嚴格相關選項的涵蓋性標記(目前為 --strict-markers--strict-config,未來可能會新增更多選項)。

實作 pytest_cmdline_preparse 掛鉤

自版本 7.0 起已標示為已棄用。

已在版本 8.0 中移除。

實作 pytest_cmdline_preparse 掛鉤已正式棄用。請改為實作 pytest_load_initial_conftests 掛鉤。

def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: ...


# becomes:


def pytest_load_initial_conftests(
    early_config: Config, parser: Parser, args: List[str]
) -> None: ...

pytest 8 中的收集變更

新增 pytest.Directory 基本收集節點,預期所有檔案系統目錄的收集器節點都繼承此類別。這類似於現有的 pytest.File 檔案節點。

變更 pytest.Packagepytest.Directory 的子類別。Package 代表一個檔案系統目錄,它是 Python 套件,也就是包含 __init__.py 檔案。

pytest.Package 現在只收集其自身目錄中的檔案;先前它會遞迴收集。子目錄會收集為子收集器節點,因此會建立一個與檔案系統階層鏡像的收集樹狀結構。

session.name 現在為 "";以前是 rootdir 目錄名稱。這符合 session.nodeid,它一直是 ""

新增一個新的 pytest.Dir 具體收集節點,pytest.Directory 的子類別。此節點代表一個檔案系統目錄,它不是 pytest.Package,也就是說,不包含 __init__.py 檔案。類似於 Package,它只收集它自己的目錄中的檔案,同時將子目錄收集為子收集器節點。

除非由外掛程式變更,否則檔案和目錄現在會以字母順序共同收集。以前,檔案是在目錄之前收集的。

對於在 rootdir 中找到的初始參數,收集樹現在包含目錄/套件,直到 rootdir。對於 rootdir 之外的檔案,只收集立即的目錄/套件 - 但請注意,不建議在 rootdir 之外收集。

舉例來說,給定以下檔案系統樹

myroot/
    pytest.ini
    top/
    ├── aaa
    │   └── test_aaa.py
    ├── test_a.py
    ├── test_b
    │   ├── __init__.py
    │   └── test_b.py
    ├── test_c.py
    └── zzz
        ├── __init__.py
        └── test_zzz.py

收集樹,如 pytest --collect-only top/ 所示,但為了清楚起見,加入了原本隱藏的 Session 節點,現在如下所示

<Session>
  <Dir myroot>
    <Dir top>
      <Dir aaa>
        <Module test_aaa.py>
          <Function test_it>
      <Module test_a.py>
        <Function test_it>
      <Package test_b>
        <Module test_b.py>
          <Function test_it>
      <Module test_c.py>
        <Function test_it>
      <Package zzz>
        <Module test_zzz.py>
          <Function test_it>

以前,它是

<Session>
  <Module top/test_a.py>
    <Function test_it>
  <Module top/test_c.py>
    <Function test_it>
  <Module top/aaa/test_aaa.py>
    <Function test_it>
  <Package test_b>
    <Module test_b.py>
      <Function test_it>
  <Package zzz>
    <Module test_zzz.py>
      <Function test_it>

依賴收集樹特定形狀的程式碼/外掛程式可能需要更新。

pytest.Package 不再是 pytest.Modulepytest.File

8.0 版中已變更。

Package 蒐集器節點指定 Python 套件,也就是包含 __init__.py 檔案的目錄。先前 Packagepytest.Module 的子類型(代表單一 Python 模組),而模組是 __init__.py 檔案。這被視為設計錯誤(請參閱 問題 #11137問題 #7777 以取得詳細資料)。

Package 節點的 path 屬性現在指向套件目錄,而非 __init__.py 檔案。

請注意,__init__.py(非 Package)的 Module 節點仍可能存在,如果它在蒐集期間被選取(例如,如果您將 python_files 設定為包含 __init__.py 檔案)。

蒐集 __init__.py 檔案不再蒐集套件

已在版本 8.0 中移除。

執行 pytest pkg/__init__.py 現在只會蒐集 pkg/__init__.py 檔案(模組)。先前,它會蒐集整個 pkg 套件,包括目錄中的其他測試檔案,但會排除 __init__.py 檔案本身的測試(除非 python_files 已變更為允許 __init__.py 檔案)。

若要蒐集整個套件,請只指定目錄:pytest pkg

pytest.collect 模組

自版本 6.0 起已棄用。

已在版本 7.0 中移除。

pytest.collect 模組不再是公開 API 的一部分,現在應直接從 pytest 匯入所有名稱。

pytest_warning_captured 掛鉤

自版本 6.0 起已棄用。

已在版本 7.0 中移除。

此掛鉤有一個 item 參數,無法由 pytest-xdist 序列化。

請改用 pytest_warning_recorded 掛鉤,它會以 nodeid 參數取代 item 參數。

pytest._fillfuncargs 函式

自版本 6.0 起已棄用。

已在版本 7.0 中移除。

保留此函式是為了與較舊的外掛程式保持向後相容性。

其功能並非供直接使用,但如果您必須取代它,請改用 function._request._fillfixtures(),但請注意這不是公開 API,未來可能會中斷。

--no-print-logs 命令列選項

自版本 5.4 起已棄用。

已於版本 6.0 中移除。

--no-print-logs 選項和 log_print ini 設定已移除。如果您使用它們,請改用 --show-capture

--show-capture 命令列選項已新增至 pytest 3.5.0,允許在測試失敗時指定如何顯示擷取的輸出:nostdoutstderrlogall(預設值)。

結果記錄 (--result-log)

自版本 4.0 起已棄用。

已於版本 6.0 中移除。

--result-log 選項會產生一串測試報告,可以在執行期間進行分析,但它使用自訂格式,要求使用者實作自己的剖析器。

pytest-reportlog 外掛程式提供 --report-log 選項,這是一個更標準且可擴充的替代方案,每行產生一個 JSON 物件,且應涵蓋相同的使用案例。請試用並提供意見回饋。

pytest-reportlog 外掛程式甚至可能在某個時間點合併到核心,具體取決於外掛程式的計畫和使用它的使用者數量。

pytest_collect_directory 掛鉤

已於版本 6.0 中移除。

pytest_collect_directory 掛鉤多年來一直無法正常運作(它已被呼叫,但結果遭到忽略)。使用者可以考慮改用 pytest_collection_modifyitems

TerminalReporter.writer

已於版本 6.0 中移除。

屬性 TerminalReporter.writer 已過時,且不應再使用。這是該外掛程式公開 API 的一部分,但無意間公開,並與 py.io.TerminalWriter 綁定過於緊密。

直接使用 TerminalReporter.writer 的外掛程式應改用 TerminalReporter 方法,以提供相同的功能。

junit_family 預設值變更為「xunit2」

在版本 6.0 中變更。

在 pytest 6.0 中,junit_family 選項的預設值將變更為 xunit2,這是舊 xunit1 格式的更新,且現代工具預設支援此格式(例如 Jenkins、Azure Pipelines 等)。

建議使用者嘗試新的 xunit2 格式,並查看使用 JUnit XML 檔案的工具是否支援此格式。

若要使用新格式,請更新您的 pytest.ini

[pytest]
junit_family=xunit2

如果您發現您的工具不支援新格式,且想要繼續使用舊版本,請將選項設定為 legacy

[pytest]
junit_family=legacy

透過使用 legacy,您將在升級至 pytest 6.0 時繼續使用舊版/xunit1 格式,而預設格式將為 xunit2

為了讓使用者知道此過渡,如果在命令列中提供 --junit-xml 選項,但未在 pytest.ini 中明確設定 junit_family,pytest 將會發出警告。

已知支援 xunit2 格式的服務

節點建構已變更為 Node.from_parent

在版本 6.0 中變更。

現在節點的建構應使用命名建構函式 from_parent。API 介面的此限制旨在讓收集樹的重構更佳/更簡單。

這表示現在必須呼叫 MyItem.from_parent(collector, name="foo"),而不是 MyItem(name="foo", parent=collector, obj=42)

想要支援較舊版本的 pytest 並抑制警告的外掛可以使用 hasattr 來檢查該版本中是否存在 from_parent

def pytest_pycollect_makeitem(collector, name, obj):
    if hasattr(MyItem, "from_parent"):
        item = MyItem.from_parent(collector, name="foo")
        item.obj = 42
        return item
    else:
        return MyItem(name="foo", parent=collector, obj=42)

請注意,from_parent 應僅與參數的關鍵字引數一起呼叫。

pytest.fixture 引數僅為關鍵字

已於版本 6.0 中移除。

已移除將引數傳遞給 pytest.fixture() 作為位置引數的功能 - 請改用關鍵字傳遞。

funcargnames 別名為 fixturenames

已於版本 6.0 中移除。

FixtureRequestMetafuncFunction 類別會追蹤其關聯固定裝置的名稱,並使用適切命名的 fixturenames 屬性。

在 pytest 2.3 之前,此屬性名為 funcargnames,而我們從那時起就將其保留為別名。由於在我們或外掛作者必須區分固定裝置名稱和非固定裝置項目(例如 pytest.mark.parametrize)提供的名稱的地方,這通常會造成混淆,因此最終會將其移除。

pytest.config 全域

已在版本 5.0 中移除。

全局物件 pytest.config 已棄用。請改用 request.config(透過 request 固定裝置),或者如果您是外掛程式作者,請使用 pytest_configure(config) 掛鉤。請注意,許多掛鉤也可以間接存取 config 物件,例如透過 session.configitem.config

"message" 參數 pytest.raises

已在版本 5.0 中移除。

認為此參數會比對例外訊息是一個常見的錯誤,但事實上它只會在 pytest.raises 檢查失敗時提供自訂訊息。為了防止使用者犯下此錯誤,且由於相信此參數使用率不高,pytest 已將其棄用,目前未提供替代方案。

如果您有此參數的有效使用案例,請考慮您可以直接在 with 陳述式的結尾手動呼叫 pytest.fail,以取得相同的結果。

例如

with pytest.raises(TimeoutError, message="Client got unexpected message"):
    wait_for(websocket.recv(), 0.5)

變成

with pytest.raises(TimeoutError):
    wait_for(websocket.recv(), 0.5)
    pytest.fail("Client got unexpected message")

如果您仍然對此棄用和未來移除感到疑慮,請在 議題 #3974 中留言。

raises / warns,第二個引數為字串

已在版本 5.0 中移除。

改用這些的內容管理員表單。必要時,直接呼叫 exec

範例

pytest.raises(ZeroDivisionError, "1 / 0")
pytest.raises(SyntaxError, "a $ b")

pytest.warns(DeprecationWarning, "my_function()")
pytest.warns(SyntaxWarning, "assert(1, 2)")

變成

with pytest.raises(ZeroDivisionError):
    1 / 0
with pytest.raises(SyntaxError):
    exec("a $ b")  # exec is required for invalid syntax

with pytest.warns(DeprecationWarning):
    my_function()
with pytest.warns(SyntaxWarning):
    exec("assert(1, 2)")  # exec is used to avoid a top-level warning

在自訂收集器中使用 Class

已在版本 4.0 中移除。

使用名為 "Class" 的物件作為自訂 Collector 子類別中收集的節點類型的方式已棄用。使用者應改用 pytest_pycollect_makeitem 在收集期間自訂節點類型。

此議題應只會影響建立新收集類型的進階外掛程式,因此如果您看到此警告訊息,請聯絡作者,以便他們變更程式碼。

pytest.mark.parametrize 中標記

已在版本 4.0 中移除。

將標記套用至 pytest.mark.parametrize 呼叫的值現已棄用。例如

@pytest.mark.parametrize(
    "a, b",
    [
        (3, 9),
        pytest.mark.xfail(reason="flaky")(6, 36),
        (10, 100),
        (20, 200),
        (40, 400),
        (50, 500),
    ],
)
def test_foo(a, b): ...

此程式碼將 pytest.mark.xfail(reason="flaky") 標記套用至上述參數化呼叫的 (6, 36) 值。

這被認為難以閱讀和理解,且其實作也對程式碼造成問題,進而阻礙標記架構進一步的內部改善。

若要更新程式碼,請使用 pytest.param

@pytest.mark.parametrize(
    "a, b",
    [
        (3, 9),
        pytest.param(6, 36, marks=pytest.mark.xfail(reason="flaky")),
        (10, 100),
        (20, 200),
        (40, 400),
        (50, 500),
    ],
)
def test_foo(a, b): ...

pytest_funcarg__ 前綴

已在版本 4.0 中移除。

在非常早期的 pytest 版本中,可以使用 pytest_funcarg__ 前綴來定義固定裝置

def pytest_funcarg__data():
    return SomeData()

切換至 @pytest.fixture 裝飾器

@pytest.fixture
def data():
    return SomeData()

[pytest] 部分在 setup.cfg 檔案中

已在版本 4.0 中移除。

[pytest] 部分在 setup.cfg 檔案中現在應命名為 [tool:pytest] 以避免與其他 distutils 指令發生衝突。

Metafunc.addcall

已在版本 4.0 中移除。

Metafunc.addcall 是當前參數化機制的先驅。使用者應改用 pytest.Metafunc.parametrize()

範例

def pytest_generate_tests(metafunc):
    metafunc.addcall({"i": 1}, id="1")
    metafunc.addcall({"i": 2}, id="2")

變成

def pytest_generate_tests(metafunc):
    metafunc.parametrize("i", [1, 2], ids=["1", "2"])

cached_setup

已在版本 4.0 中移除。

request.cached_setup 是提供給固定裝置的設定/清除機制的先驅。

範例

@pytest.fixture
def db_session():
    return request.cached_setup(
        setup=Session.create, teardown=lambda session: session.close(), scope="module"
    )

這應該更新為使用標準固定裝置機制

@pytest.fixture(scope="module")
def db_session():
    session = Session.create()
    yield session
    session.close()

你可以參閱 文件中的 funcarg 比較區段 以取得更多資訊。

非頂層 conftest 檔案中的 pytest_plugins

已在版本 4.0 中移除。

在非頂層 conftest.py 檔案中定義 pytest_plugins 現在已過時,因為它們會全域性地啟用所參考的套件,這很令人驚訝,因為對於所有其他 pytest 功能,conftest.py 檔案僅對其本身或其以下的測試有效

Config.warnNode.warn

已在版本 4.0 中移除。

這些方法是內部 pytest 警告系統的一部分,但自 3.8 以來,pytest 已為其自己的警告使用內建警告系統,因此這兩個函式現在已過時。

Config.warn 應改為呼叫標準 warnings.warn,範例

config.warn("C1", "some warning")

變成

warnings.warn(pytest.PytestWarning("some warning"))

Node.warn 現在支援兩個簽章

  • node.warn(PytestWarning("some message")):現在是呼叫此函式的建議方式。警告實例必須是 PytestWarning 或其子類別。

  • node.warn("CI", "some message"):此程式碼/訊息格式已移除,應轉換為上述警告實例格式。

record_xml_property

已在版本 4.0 中移除。

record_xml_property 固定裝置現在已過時,取而代之的是更通用的 record_property,其他消費者(例如 pytest-html)可以使用它來取得關於測試執行的自訂資訊。

這只是重新命名固定裝置,因為 API 是相同的

def test_foo(record_xml_property): ...

變更為

def test_foo(record_property): ...

傳遞命令列字串給 pytest.main()

已在版本 4.0 中移除。

傳遞命令列字串給 pytest.main() 已過時

pytest.main("-v -s")

改為傳遞清單

pytest.main(["-v", "-s"])

傳遞字串時,使用者預期 pytest 會使用他們正在使用的 shell 規則來詮釋該命令列(例如 bashPowershell),但這在可攜式方式中非常困難/不可能。

直接呼叫固定裝置

已在版本 4.0 中移除。

直接呼叫固定裝置函式(而非在測試函式中要求它們)已過時。

例如

@pytest.fixture
def cell():
    return ...


@pytest.fixture
def full_cell():
    cell = cell()
    cell.make_full()
    return cell

這會讓新使用者感到非常困惑,他們經常會交替呼叫固定裝置函式和從測試函式要求它們,這會中斷固定裝置解析模型。

在這些情況下,只要直接在相依固定裝置中要求函式即可

@pytest.fixture
def cell():
    return ...


@pytest.fixture
def full_cell(cell):
    cell.make_full()
    return cell

或者,如果在測試中多次呼叫固定裝置函式(這使得難以套用上述模式),或者如果您想對程式碼進行最小的變更,您可以建立一個固定裝置,它會呼叫原始函式以及 name 參數

def cell():
    return ...


@pytest.fixture(name="cell")
def cell_fixture():
    return cell()

yield 測試

已在版本 4.0 中移除。

pytest 支援 yield 樣式測試,其中測試函式實際上會 yield 函式和值,然後將其轉換為適當的測試方法。範例

def check(x, y):
    assert x**x == y


def test_squared():
    yield check, 2, 4
    yield check, 3, 9

這將導致產生兩個實際的測試函式。

這種形式的測試函式無法適當地支援固定裝置,使用者應改用 pytest.mark.parametrize

@pytest.mark.parametrize("x, y", [(2, 4), (3, 9)])
def test_squared(x, y):
    assert x**x == y

透過 Node 存取的內部類別

已在版本 4.0 中移除。

透過 Node 實例存取 ModuleFunctionClassInstanceFileItem 現在會發出此警告

usage of Function.Module is deprecated, please use pytest.Module instead

使用者應僅 import pytest 並使用 pytest 模組存取這些物件。

這已被記錄為已棄用多年,但直到現在我們才實際發出棄用警告。

Node.get_marker

已在版本 4.0 中移除。

作為大型 標記改造和迭代 的一部分,_pytest.nodes.Node.get_marker 已移除。請參閱 文件,了解如何更新您的程式碼的提示。

somefunction.markname

已在版本 4.0 中移除。

作為大型 標記改造和迭代 的一部分,我們已經不建議使用 MarkInfo,取得元素標記的唯一正確方式是透過 node.iter_markers(name)

pytest_namespace

已在版本 4.0 中移除。

此掛鉤已棄用,因為它極大地複雜化了 pytest 內部關於組態和初始化的內容,使得一些錯誤修正和重構變得不可能。

使用範例

class MySymbol: ...


def pytest_namespace():
    return {"my_symbol": MySymbol()}

依賴此掛鉤的外掛作者應該要求使用者現在直接匯入外掛模組(具有適當的公開 API)。

作為權宜措施,外掛作者仍可以在 pytest_configure 期間將其名稱注入 pytest 的命名空間。

import pytest


def pytest_configure():
    pytest.my_symbol = MySymbol()