2014-02-05 130 views
12

比方說,我有一個簡單的燈具,如以下(使用pytest-Django的,但我認爲它應該適用於pytest以及):多個副本

@pytest.fixture 
def my_thing(request, db): 
    thing = MyModel.objects.create() 
    request.addfinalizer(lambda: thing.delete()) 
    return thing 

這個偉大的工程時我的測試需要一個MyModel實例。但是如果我需要兩個(或三個或四個)呢?我希望每個實例都是獨特的,但要以相同的方式進行設置。

我可以複製/粘貼代碼並重命名燈具功能,但看起來不夠雅緻。

同樣,我曾嘗試:

@pytest.fixture 
def my_thing_1(my_thing): 
    return my_thing 

@pytest.fixture 
def my_thing_2(my_thing): 
    return my_thing 

然而,這些出現的迴歸爲MyModel的同一個實例。

有沒有辦法用pytest的內置功能來做我想做的事?或者,我可以將我的燈具的設置/拆卸轉換爲輔助函數,這樣我就不會複製太多的代碼。

或者我是否以錯誤的方式處理這件事?

回答

17

我的方法可能會創建一個夾具,可以生成你的對象:

@pytest.fixture 
def thing(request, db): 
    class ThingFactory(object): 
     def get(self): 
      thing = MyModel.objects.create() 
      request.addfinalizer(thing.delete) 
      return thing 
    return ThingFactory() 

def test_thing(thing): 
    thing1 = thing.get() 
    thing2 = thing.get() 

很明顯,你可以讓.get()帶參數等

(PS:另外請注意沒有必要爲拉姆達在終結者)

+1

1)不需要在拉姆達終結良好的通話。 2)我喜歡你的方法。我實際上是使用Factory Boy來創建這些模型,所以我認爲我甚至不需要爲每個模型創建工廠固定裝置。但是我無法繼承ModelFactory以遞歸添加子工廠的終結器,所以我想我會使用您的方法作爲停止缺口。謝謝! –

+1

爲了將來的參考,我使用finalizer的唯一原因是pytest-django沒有在兩次測試之間清理數據庫,因爲它不支持多個數據庫(另請參閱https://github.com/pelme/pytest_django/issues/ 76)。對於上面描述的問題類型,我衷心推薦使用帶有pytest-django的FactoryBoy。 –

0

我很晚纔到達這個問題......但是,使用參數化夾具,並簡單地返回你想要複製的夾具似乎也工作。

import pytest 
import random 

@pytest.fixture 
def name(): 
    return random.randint(0, 10) 


@pytest.fixture(params=[0, 1]) 
def parametrized_name(request, name): 
    return name 


def test_something(parametrized_name): 
    print "Testing with name: " + str(parametrized_name) 

如果你運行上面的測試,你就會得到2個不同的「名字」燈具

$ pytest -s blah.py 
============================================= test session starts ============================================== 
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.2, pluggy-0.6.0 
rootdir: /home/bsquizza/repos/blah/tests, inifile: 
collected 2 items                        

blah.py Testing with name: 7 
.Testing with name: 10 
.                        [100%] 

=========================================== 2 passed in 0.01 seconds ===========================================