我正在尝试以一种不错的方式解决这个问题,但似乎无法使其正常工作。
假设我要测试以下业务逻辑:
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个。
答案 0 :(得分:1)
如果要使用多个耦合参数(data
和expected
),则只需将它们组合在单个夹具中或在单个parametrize
调用中,否则夹具将始终如您所见组合在一起:
@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]
或使用字典来提高可读性:
@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
:
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
可能是更好的选择,因为单独的参数使其更具可读性。如果您想在多个测试中使用参数,并且测试数据的读取范围很广,则夹具可能是更好的选择。
请注意,还可以选择对pytest_generate_tests
中的测试进行参数化,其效果与向所有或某些测试中添加mark.parametrize
装饰器相同。