gpt4 book ai didi

python - 在 pytest 测试类中使用 @mark.incremental 和 metafunc.parametrize

转载 作者:太空宇宙 更新时间:2023-11-04 05:22:10 25 4
gpt4 key购买 nike

@mark.incremental 的目的是如果一个测试失败,之后的测试将被标记为预期失败。

但是,当我将它与参数化结合使用时,我会出现不良行为。

例如,在这个假代码的情况下:

//conftest.py:

def pytest_generate_tests(metafunc):
metafunc.parametrize("input", [True, False, None, False, True])

def pytest_runtest_makereport(item, call):
if "incremental" in item.keywords:
if call.excinfo is not None:
parent = item.parent
parent._previousfailed = item

def pytest_runtest_setup(item):
if "incremental" in item.keywords:
previousfailed = getattr(item.parent, "_previousfailed", None)
if previousfailed is not None:
pytest.xfail("previous test failed (%s)" %previousfailed.name)

//test.py:
@pytest.mark.incremental
class TestClass:
def test_input(self, input):
assert input is not None
def test_correct(self, input):
assert input==True

我希望测试类能够运行

  • test_input 为真,

  • 紧随其后的是 test_correct,

  • 紧随其后的是 False 上的 test_input,

  • 随后是 test_correct 错误,

  • 紧随其后的是无测试输入,

  • 后跟 (xfailed) test_correct on None,等等。

相反,发生的是测试类

  • 在 True 上运行 test_input,
  • 然后在 False 上运行 test_input,
  • 然后在 None 上运行 test_input,
  • 然后将从该点开始的所有内容标记为 xfailed(包括 test_corrects)。

我假设正在发生的事情是参数化优先于通过类中的函数进行处理。问题是是否有可能覆盖此行为或以某种方式解决它,因为当前情况使将类标记为增量对我来说完全没用。

(处理这个问题的唯一方法是一遍又一遍地复制粘贴类的代码,每次都使用不同的参数吗?这个想法让我厌恶)

最佳答案

https://docs.pytest.org/en/latest/example/parametrize.html 中描述了此问题的解决方案在标题 “testscenarios”的快速端口下

这是那里列出的代码,conftest.py 中的代码正在做的是在测试类中寻找变量 scenarios。当它找到变量时,它会遍历场景的每个项目,并需要一个 id 字符串来标记测试和一个“argnames:argvalues”字典

# content of conftest.py
def pytest_generate_tests(metafunc):
idlist = []
argvalues = []
for scenario in metafunc.cls.scenarios:
idlist.append(scenario[0])
items = scenario[1].items()
argnames = [x[0] for x in items]
argvalues.append(([x[1] for x in items]))
metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")

# content of test_scenarios.py
scenario1 = ('basic', {'attribute': 'value'})
scenario2 = ('advanced', {'attribute': 'value2'})

class TestSampleWithScenarios(object):
scenarios = [scenario1, scenario2]

def test_demo1(self, attribute):
assert isinstance(attribute, str)

def test_demo2(self, attribute):
assert isinstance(attribute, str)

您还可以修改函数 pytest_generate_tests 以接受不同的数据类型输入。例如,如果您有一个通常传递给的列表@pytest.mark.parametrize("varname", varval_list)您可以通过以下方式使用相同的列表:

# content of conftest.py
def pytest_generate_tests(metafunc):
idlist = []
argvalues = []
argnames = metafunc.cls.scenario_keys
for idx, scenario in enumerate(metafunc.cls.scenario_parameters):
idlist.append(str(idx))
argvalues.append([scenario])
metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")

# content of test_scenarios.py
varval_list = [a, b, c, d]
class TestSampleWithScenarios(object):
scenario_parameters = varval_list
scenario_keys = ['varname']

def test_demo1(self, attribute):
assert isinstance(attribute, str)

def test_demo2(self, attribute):
assert isinstance(attribute, str)

id 将是一个自动生成的数字(您可以将其更改为使用您指定的内容)并且在此实现中它不会处理多个参数化变量,因此您必须将它们编译在一个列表中(或满足 pytest_generate_tests 为你处理)

关于python - 在 pytest 测试类中使用 @mark.incremental 和 metafunc.parametrize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39898702/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com