關於固定裝置

另請參閱

固定裝置參考

pytest 固定裝置的設計目標是明確、模組化和可擴充。

固定裝置是什麼

在測試中,固定裝置為測試提供定義明確、可靠且一致的環境。這可能包括環境(例如已設定已知參數的資料庫)或內容(例如資料集)。

固定裝置定義構成測試安排階段的步驟和資料(請參閱測試解剖)。在 pytest 中,它們是您定義用於此目的的函式。它們也可以用於定義測試的行為階段;這是一種設計更複雜測試的強大技術。

測試函式透過參數存取由固定裝置設定的服務、狀態或其他作業環境。測試函式使用的每個固定裝置通常在測試函式定義中有一個參數(以固定裝置命名)。

我們可以透過使用 @pytest.fixture 裝飾器來告訴 pytest 特定函式是一個固定裝置。以下是一個 pytest 中固定裝置的簡單範例

import pytest


class Fruit:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name


@pytest.fixture
def my_fruit():
    return Fruit("apple")


@pytest.fixture
def fruit_basket(my_fruit):
    return [Fruit("banana"), my_fruit]


def test_my_fruit_in_basket(my_fruit, fruit_basket):
    assert my_fruit in fruit_basket

測試也不必侷限於單一固定裝置。它們可以依賴於您想要的任意數量的固定裝置,而固定裝置也可以使用其他固定裝置。這正是 pytest 固定裝置系統真正發揮作用的地方。

相較於 xUnit 風格的設定/清除函式,所做的改進

pytest 固定裝置相較於經典 xUnit 風格的設定/清除函式提供了顯著的改進

  • 固定裝置有明確的名稱,並透過宣告從測試函式、模組、類別或整個專案使用它們來啟動。

  • 固定裝置是以模組化方式實作,因為每個固定裝置名稱都會觸發固定裝置函式,而固定裝置函式本身可以使用其他固定裝置。

  • 固定裝置管理的範圍從簡單的單元測試到複雜的功能測試,允許根據設定和元件選項參數化固定裝置和測試,或在函式、類別、模組或整個測試階段範圍內重複使用固定裝置。

  • 清除邏輯可以輕鬆且安全地管理,無論使用多少固定裝置,無需仔細手動處理錯誤或微觀管理清除步驟的順序。

此外,pytest 繼續支援 如何實作 xunit 風格設定。您可以混合兩種風格,依您的喜好從傳統風格逐步轉移到新風格。您也可以從現有的 unittest.TestCase 風格 開始。

固定裝置錯誤

pytest 會盡力將給定測試的所有固定裝置依線性順序排列,以便它可以看出哪個固定裝置先發生、哪個第二、哪個第三,以此類推。不過,如果較早的固定裝置遇到問題並引發例外,pytest 會停止執行該測試的固定裝置,並將測試標示為有錯誤。

不過,當測試被標示為有錯誤時,並不表示測試失敗。這只表示測試甚至無法嘗試,因為它依賴的其中一項發生問題。

這就是為什麼盡可能減少給定測試的不必要依賴關係是很好的原因之一。這樣一來,不相關的事項發生問題就不會導致我們對可能有或沒有問題的事物產生不完整的印象。

以下是說明的快速範例

import pytest


@pytest.fixture
def order():
    return []


@pytest.fixture
def append_first(order):
    order.append(1)


@pytest.fixture
def append_second(order, append_first):
    order.extend([2])


@pytest.fixture(autouse=True)
def append_third(order, append_second):
    order += [3]


def test_order(order):
    assert order == [1, 2, 3]

如果 order.append(1) 因為任何原因而有錯誤並引發例外,我們將無法得知 order.extend([2])order += [3] 是否也有問題。在 append_first 引發例外後,pytest 將不會再為 test_order 執行任何固定裝置,甚至不會嘗試執行 test_order 本身。唯一會執行的只有 orderappend_first

分享測試資料

如果您想讓測試從檔案取得測試資料,一個好方法是載入這些資料到固定裝置中,供您的測試使用。這會使用 pytest 的自動快取機制。

另一種好方法是將資料檔新增到 tests 資料夾中。也有社群外掛可用於協助管理測試的這個面向,例如 pytest-datadirpytest-datafiles

關於 fixture 清理的說明

pytest 對於 SIGTERMSIGQUIT 訊號並未執行任何特殊處理(SIGINT 由 Python 執行時期透過 KeyboardInterrupt 自然處理),因此管理外部資源的 fixture,在 Python 程序終止(透過這些訊號)時清除這些資源非常重要,否則可能會造成資源外洩。

pytest 不處理這些訊號來執行 fixture 清理的原因是訊號處理常式是全域的,而變更它們可能會干擾執行中的程式碼。

如果組件中的 fixture 在這些情況下需要特別注意終止,請參閱問題追蹤器中的 這則留言 以取得可能的解決方法。