簡體   English   中英

我可以將參數傳遞給 pytest 固定裝置嗎?

[英]Can I pass arguments to pytest fixtures?

我所有測試的基准是,總會有一輛至少載有一名乘客的出租車。 我可以使用一些基本裝置輕松實現此設置:

from blah import Passenger, Taxi

@pytest.fixture
def passenger():
    return Passenger()

@pytest.fixture
def taxi(passenger):
    return Taxi(rear_seat=passenger)

測試基線很簡單:

def test_taxi_contains_passenger(taxi)
    assert taxi.has_passenger()

當我開始需要更復雜的測試設置時,我的問題就出現了。 在某些情況下,我需要出租車有不止一名乘客,以及需要定義乘客屬性的情況。 例如:

def test_three_passengers_in_taxi(taxi)
    assert taxi.has_passengers(3)
    assert taxi.front_passenger_is_not_a_child()

我可以通過為特定測試使用特定裝置來解決這個問題。 對於上述測試,我將創建以下夾具:

@pytest.fixture
def three_passenger_test_setup(taxi)
    taxi.add_front_seat_passenger(Passenger(child=False))
    taxi.add_rear_seat_passenger(Passenger())
    return taxi

我可以將上面的夾具傳遞到我的測試用例中,一切都很好,但是如果我沿着這條路走下去,我可能會為每個測試最終得到一個夾具,感覺應該有一種更有效的方法來做到這一點。

有沒有辦法將參數傳遞給夾具,以便這些參數可以用於創建夾具返回的對象? 我應該參數化測試函數嗎? 夾具? 或者我是在浪費時間,每次測試都需要一個固定裝置嗎?

我們可以通過使用一個方法來實現這一點,該方法在夾具中接受 args 並從夾具中返回該方法。

讓我給你看一個例子

@pytest.fixture
def my_fixture():

  def _method(a, b):
    return a*b

  return _method

def test_me(my_fixture):
  result1 = my_fixture(2, 3)
  assert result1 == 6

  result2 = my_fixture(4, 5)
  assert result2 == 20

有沒有辦法將參數傳遞給夾具,以便這些參數可以用於創建夾具返回的對象? 我應該參數化測試函數嗎?

您可以將測試參數化與indirect=True 在 pytest 文檔中: 在特定參數上應用間接 如此處所示: https : //stackoverflow.com/a/33879151/3858507


夾具?

另一個可能適合您的選項是使用一些使用參數化指定參數的夾具:

@pytest.fixture(params=[3,4])
def number_of_passengers(request):
    return request.param

然后從出租車和測試本身訪問這個裝置:

@pytest.fixture
def taxi(number_of_passengers):
    return Taxi(rear_seat=Passenger() * number_of_passengers)

def test_three_passengers_in_taxi(taxi, number_of_passengers)
    assert taxi.has_passengers(number_of_passengers)
    assert taxi.front_passenger_is_not_a_child()

如果您的測試和斷言在您擁有的案例之間非常相似,則這種方式很好。


或者我是在浪費時間,每次測試都需要一個固定裝置嗎?

我會說你絕對不應該為每個測試函數創建一個夾具。 為此,您可以將設置放入測試中。 在您必須為出租車的不同情況做出不同斷言的情況下,這實際上是一個可行的選擇。


最后,您可以使用的另一種可能模式是出租車工廠。 對於您提供的示例,它不是很有用,如果需要多個參數並且只有一些參數在更改,您可以創建一個類似於以下內容的夾具:

from functools import partial
@pytest.fixture
def taxi_factory():
    return partial(Taxi, 1, 2, 3)

fixture只是一個 Python 裝飾器。

@decorator
def function(args):
  ...

很喜歡

def function(args):
  ...
function = decorator(function)

因此,您也許可以編寫自己的裝飾器,將您想要裝飾的功能包裝在您需要的任何東西fixture

def myFixture(parameter):
  def wrapper(function):
    def wrapped(*args, **kwargs):
      return function(parameter, *args, **kwargs)
    return wrapped
  return pytest.fixture(wrapper)

@myFixture('foo')
def function(parameter, ...):
  ...

這將像fixture一樣工作,但會將值( 'foo' )作為parameter傳遞給function

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM