pytest fixture-作用域:class、module、package或session共享fixture

2022-03-18 14:07 更新

需要網(wǎng)絡訪問的??fixture??依賴于連接,通常需要花費大量的時間來創(chuàng)建。擴展前面的例子,我們可以給??@pytest??添加一個??scope="module"??參數(shù)。??fixture??調用??smtp_connection fixture??函數(shù),該函數(shù)負責創(chuàng)建到先前存在的SMTP服務器的連接,每個測試模塊只調用一次(默認情況下是每個測試函數(shù)調用一次)。因此,一個測試模塊中的多個測試函數(shù)將接收相同的??smtp_connection fixture??實例,從而節(jié)省時間。作用域的可能值有:函數(shù)、類、模塊、包或會話。

下一個示例將??fixture ??函數(shù)放入一個單獨的??conftest.py?? 文件中,以便目錄中多個測試模塊的測試可以訪問??fixture??函數(shù):

# content of conftest.py
import pytest
import smtplib


@pytest.fixture(scope="module")
def smtp_connection():
    return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
# content of test_module.py


def test_ehlo(smtp_connection):
    response, msg = smtp_connection.ehlo()
    assert response == 250
    assert b"smtp.gmail.com" in msg
    assert 0  # for demo purposes


def test_noop(smtp_connection):
    response, msg = smtp_connection.noop()
    assert response == 250
    assert 0  # for demo purposes

在這里, ??test_ehlo ??需要 ??smtp_connection fixture??值。 ?pytest ?將發(fā)現(xiàn)并調用 ??@pytest.fixture?? 標記的 ??smtp_connection fixture??函數(shù)。 運行測試如下所示:

$ pytest test_module.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 2 items

test_module.py FF                                                    [100%]

================================= FAILURES =================================
________________________________ test_ehlo _________________________________

smtp_connection = <smtplib.SMTP object at 0xdeadbeef0001>

    def test_ehlo(smtp_connection):
        response, msg = smtp_connection.ehlo()
        assert response == 250
        assert b"smtp.gmail.com" in msg
>       assert 0  # for demo purposes
E       assert 0

test_module.py:7: AssertionError
________________________________ test_noop _________________________________

smtp_connection = <smtplib.SMTP object at 0xdeadbeef0001>

    def test_noop(smtp_connection):
        response, msg = smtp_connection.noop()
        assert response == 250
>       assert 0  # for demo purposes
E       assert 0

test_module.py:13: AssertionError
========================= short test summary info ==========================
FAILED test_module.py::test_ehlo - assert 0
FAILED test_module.py::test_noop - assert 0
============================ 2 failed in 0.12s =============================

您會看到兩個 ??assert 0?? 失敗,更重要的是,您還可以看到完全相同的 ??smtp_connection?? 對象被傳遞到兩個測試函數(shù)中,因為 pytest 在回溯中顯示了傳入的參數(shù)值。 因此,使用 ??smtp_connection?的兩個測試函數(shù)的運行速度與單個測試函數(shù)一樣快,因為它們重用了相同的實例。

如果你想要一個會話作用域的??smtp_connection??實例,你可以簡單地聲明它:

@pytest.fixture(scope="session")
def smtp_connection():
    # the returned fixture value will be shared for
    # all tests requesting it
    ...

Fixture作用域

??fixture??在第一次被測試請求時被創(chuàng)建,并根據(jù)它們的作用域被銷毀:

  • ??function??:默認作用域,??fixture??在測試結束時銷毀。
  • ??class??:在?class?中的最后一個測試拆除期間,??fixture??被銷毀。
  • ??module??:在?module?的最后一次測試拆卸時,??fixture??被破壞。
  • ??package??:在?package?中的最后一次測試拆卸時,??fixture??被破壞。
  • ??session??:?fixture?在測試session結束時被銷毀。

Pytest一次只緩存一個??fixture??的一個實例,這意味著當使用參數(shù)化的??fixture??時,Pytest可以在給定范圍內多次調用一個??fixture??。

動態(tài)作用域

在某些情況下,您可能希望更改??fixture??的作用域而不更改代碼。為此,將一個可調用對象傳遞給??scope??。該可調用對象必須返回一個具有有效作用域的字符串,并且只會執(zhí)行一次——在??fixture??定義期間。它將使用兩個關鍵字參數(shù)調用——??fixture_name??作為字符串,??config??使用配置對象。

這在處理需要時間安裝的??fixture??時特別有用,比如生成一個??docker??容器。您可以使用命令行參數(shù)來控制派生容器在不同環(huán)境下的作用域。參見下面的示例。

def determine_scope(fixture_name, config):
    if config.getoption("--keep-containers", None):
        return "session"
    return "function"


@pytest.fixture(scope=determine_scope)
def docker_container():
    yield spawn_container()


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號