如何在Pytest中向fixture函数传递参数?

253
我正在使用py.test来测试一些封装在Python类MyTester中的DLL代码。 为了验证目的,在测试过程中我需要记录一些测试数据,并在之后进行更多的处理。由于我有很多test_...文件,我希望能够重用测试对象的创建(即MyTester的实例)来进行大部分的测试。
由于测试对象是唯一拥有对DLL变量和函数的引用的对象,因此我需要为每个测试文件将DLL变量的列表传递给测试对象(对于一个test_...文件,要记录的变量是相同的)。 列表的内容用于记录指定的数据。
我的想法是以某种方式来实现这个目标:
import pytest

class MyTester():
    def __init__(self, arg = ["var0", "var1"]):
        self.arg = arg
        # self.use_arg_to_init_logging_part()

    def dothis(self):
        print "this"

    def dothat(self):
        print "that"

# located in conftest.py (because other test will reuse it)

@pytest.fixture()
def tester(request):
    """ create tester object """
    # how to use the list below for arg?
    _tester = MyTester()
    return _tester

# located in test_...py

# @pytest.mark.usefixtures("tester") 
class TestIt():

    # def __init__(self):
    #     self.args_for_tester = ["var1", "var2"]
    #     # how to pass this list to the tester fixture?

    def test_tc1(self, tester):
       tester.dothis()
       assert 0 # for demo purpose

    def test_tc2(self, tester):
       tester.dothat()
       assert 0 # for demo purpose

这样做是否可行,或者是否有更加优雅的方式呢?
通常我可以为每个测试方法使用某种设置函数(类似于xUnit风格)。但我想要实现一些重用性。有人知道是否可以通过固定装置来实现吗?
我知道可以像这样做:(来自文档)
@pytest.fixture(scope="module", params=["merlinux.eu", "mail.python.org"])

但是我需要直接在测试模块中进行参数化。 是否可以从测试模块访问夹具的params属性?
12个回答

0

Fixture 的作用类似于装饰器。我认为这样更容易理解清晰明了。你也可以使用它。

在 conftest.py 中使用。

@pytest.fixture
def tester():
    def wrapper(arg):
        _tester = MyTester(arg)
        return _tester
    return wrapper

在test.py中

class TestIt():

   def test_tc1(self, tester, arg):  # test function takes fixture and arg
   mock_tester = tester(arg)  # mock_tester just an instance of MyTester
   mock_tester.dothis()  # so you get instance with initialized arg
   assert 0 # for demo purpose

你能提供MyTester类的实现吗?谢谢。 - undefined

0
在我的情况下,我需要在夹具的拆除过程中通过请求的id来删除一个请求。问题是只有在测试期间我才能获取到请求的id。因此,我需要一个夹具,在测试过程中接受一个参数,并在测试结束后删除我的请求。我想到了以下的解决方案:
@pytest.fixture()
def delete_request():
    # setUp:
    local_request_id = None

    def get_request_id_from_test(request_id: int):
        nonlocal local_request_id
        local_request_id = request_id

    yield get_request_id_from_test

    # tearDown:
    api.delete_request(local_request_id)

def test_create_request(delete_request):
    # Array
    ...

    # Act
    ... # here i get request id after creating a request
    delete_request(request_id)
   
    ...

这个决定不需要任何标记和参数化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接