python-3.x PyTest参数化多个夹具

x8diyxa7  于 2023-04-13  发布在  Python
关注(0)|答案(2)|浏览(184)

我试着用一种好的方式来解决这个问题,但似乎不能让它工作。
假设我有以下业务逻辑要测试:

class MyClass:
    def __init__(self, value):
        self.value = value

    def execute(self):
        return self.value

以及以下测试用例:

test_cases = [
    {
        'name': "assert True",
        'data': True,
        'expected': False
    }, {
        'name': "assert False",
        'data': False,
        'expected': True
    }
]

然后我想编写以下测试套件:

def idfn(val):
    return val.get('name')

@pytest.fixture(params=test_cases, ids=idfn)
def my_class(request):
    return MyClass(request.param['data'])

@pytest.fixture(params=test_cases, ids=idfn)
def expected(request):
    return request.param['expected']

class Test():
    def test_execute(self, my_class, expected):
        assert my_class.execute() == expected

我如何避免pytest做每一个可能的测试用例组合?我想只生成2个测试,因为我有2个测试用例,但PyTest正在生成4个。

wkftcu5l

wkftcu5l1#

如果你想使用多个耦合参数(dataexpected),你只需要在一个fixture或一个parametrize调用中合并它们,否则fixture将总是像你看到的那样组合:

@pytest.fixture(params=test_cases, ids=idfn)
def my_class_cases(request):
    return MyClass(request.param['data']), request.param['expected']

class Test:
    def test_execute(self, my_class_cases):
        assert my_class_cases[0].execute() == my_class_cases[1]

或者为了可读性使用dict:

@pytest.fixture(params=test_cases, ids=idfn)
def my_class_cases(request):
    return {'class': MyClass(request.param['data']),
            'expected': request.param['expected']}

class Test:
    def test_execute(self, my_class_cases):
        assert my_class_cases['class'].execute() == my_class_cases['expected']

在您的例子中,您也可以直接使用mark.parametrize而不使用fixture:

def get_test_params():
    return [(MyClass(case['data']), case['expected']) for case in test_cases]

def getids():
    return [case['name'] for case in test_cases]

class Test:
    @pytest.mark.parametrize("my_class,data", get_test_params(), ids=getids())
    def test_execute(self, my_class, data):
        assert my_class.execute() == data

选择哪一个是一个品味的问题。
在这种情况下,使用mark.parametrize可能是更好的选择,因为单独的参数使它更好地可读。如果你想在多个测试中使用参数,那么fixture可能是更好的选择,并且testdata的阅读是扩展的。
请注意,还有一个选项可以参数化pytest_generate_tests中的测试,这与将mark.parametrize装饰器添加到所有或部分测试具有相同的效果。

41zrol4v

41zrol4v2#

  • 所以我们有一个类用户,有名字和年龄
  • 需要名称和年龄参数的类构造函数
  • 在赛程中我们派出帕尔马斯作为[(“swapnil-1”,23),(“swapnil-2”,25)]
  • 在示例化用户类时,
  • user(request.param[0],request.param[1])用作request。name传递param[0],age传递request.param[1]
class user:
    def __init__(self,name,age):
        self.name = name
        self.age = age
class Test_parameterize:

    @pytest.fixture(scope='class',params=[("swapnil-1",25),("swapnil-2",27)])
    def dummy_usr_obj(self, request):
    
         obj = user(request.param[0],request.param[1])
         yield obj
        obj = None

    def test_user(self,dummy_usr_obj):
    
        print("--user name :  {0} user age {1} ".format(dummy_usr_obj.name, dummy_usr_obj.age))

相关问题