關於 fixtures¶
參見
pytest fixtures 旨在明確、模組化和可擴展。
什麼是 fixtures¶
在測試中,fixture 為測試提供已定義、可靠且一致的上下文。這可能包括環境(例如,配置了已知參數的資料庫)或內容(例如,資料集)。
Fixtures 定義了構成測試安排階段的步驟和資料(請參閱 測試的結構)。在 pytest 中,它們是您定義的用於此目的的函數。它們也可以用於定義測試的執行階段;這是一種設計更複雜測試的強大技術。
由 fixtures 建立的服務、狀態或其他操作環境通過參數由測試函數存取。對於測試函數使用的每個 fixture,在測試函數的定義中通常都有一個參數(以 fixture 命名)。
我們可以通過使用 @pytest.fixture
裝飾器來告訴 pytest 特定函數是 fixture。以下是 pytest 中 fixture 可能看起來像的簡單範例
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
測試也不必僅限於單個 fixture。它們可以依賴您想要的任意數量的 fixtures,並且 fixtures 也可以使用其他 fixtures。這就是 pytest 的 fixture 系統真正閃耀的地方。
相較於 xUnit 風格 setup/teardown 函數的改進¶
pytest fixtures 相較於經典的 xUnit 風格 setup/teardown 函數提供了顯著的改進
fixtures 具有明確的名稱,並通過從測試函數、模組、類別或整個專案宣告其使用來啟動。
fixtures 以模組化方式實作,因為每個 fixture 名稱都會觸發一個fixture 函數,該函數本身可以使用其他 fixtures。
fixture 管理範圍從簡單的單元測試到複雜的功能測試,允許根據配置和組件選項參數化 fixtures 和測試,或在函數、類別、模組或整個測試會話範圍內重複使用 fixtures。
可以輕鬆且安全地管理 teardown 邏輯,無論使用了多少 fixtures,而無需手動仔細處理錯誤或微觀管理添加清理步驟的順序。
此外,pytest 繼續支援 如何實作 xunit 風格的設定。您可以混合使用這兩種風格,根據您的喜好從經典風格逐步轉向新風格。您也可以從現有的 unittest.TestCase 風格 開始。
Fixture 錯誤¶
pytest 會盡力將給定測試的所有 fixtures 放在線性順序中,以便它可以查看哪個 fixture 首先、第二、第三等等。但是,如果較早的 fixture 出現問題並引發異常,pytest 將停止執行該測試的 fixtures,並將該測試標記為發生錯誤。
當測試被標記為發生錯誤時,並不意味著測試失敗了。這僅表示由於測試依賴的某個事物出現問題,因此甚至無法嘗試進行測試。
這就是為什麼盡可能減少給定測試的不必要依賴關係是個好主意的原因之一。這樣,不相關的事物出現問題就不會導致我們對可能存在或可能不存在問題的事物產生不完整的畫面。
這是一個快速範例,有助於解釋
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
運行更多 fixtures,甚至不會嘗試運行 test_order
本身。唯一會運行的將是 order
和 append_first
。
關於 fixture 清理的注意事項¶
pytest 不會對 SIGTERM
和 SIGQUIT
信號執行任何特殊處理(SIGINT
由 Python 運行時通過 KeyboardInterrupt
自然處理),因此,管理外部資源的 fixtures 在 Python 進程被(這些信號)終止時,若這些外部資源需要被清除,則可能會洩漏資源。
pytest 不處理這些信號以執行 fixture 清理的原因是信號處理程序是全域的,並且更改它們可能會干擾正在執行的代碼。
如果您的套件中的 fixtures 在這些情況下需要特別注意終止,請參閱問題追蹤器中的 此評論,以獲取可能的解決方法。