根据 py.test 中的参数跳过测试

Skip test depending on parameter in py.test

我有一个带有 session 范围的测试夹具,它是参数化的,例如

@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture():
    ...

在我的目录中,我有使用 pytest.mark.usefixtures("myfixture") 的文件和一个包含测试的文件应该是 运行 仅适用于 myfixture 参数 "two" 和 py.test 否则应该跳过它。

有什么方法可以在 py.test 中实现这一点,或者我是否需要在 myfixture() 函数中的某些 class 中设置一个特殊变量?

自己找到解决方案,可以在conftest.py中定义函数:

def pytest_namespace():
    return {"param": None}

而在 fixture 函数中我们可以做:

@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture():
    pytest.param = request.param
    # ...

所以我们可以将测试 class 包装成:

@pytest.mark.skipif("pytest.param == 'value'")
class TestSmth(object):
    ...

我在尝试解决类似用例时遇到了这个问题。我的解决方案,以防它帮助任何人避免几个小时。这是一种从测试中覆盖夹具参数化的简单方法:

@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture():
    ...

@pytest.mark.parameterize('myfixture', ['two'], indirect=True)
def test1(myfixture):
    ...

def test2(myfixture):
    ...

感谢https://hackebrot.github.io/pytest-tricks/mark_parametrize_with_indirect/解释间接的用法!

最简洁的方法是使用 pytest_collection_modifyitems 挂钩在测试集合被 运行

之前修改它们

鉴于您的灯具描述:

@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture(request):
    ...

为您的测试添加自定义标记:

@pytest.mark.restriction("two")
def test_smth(self, myfixture):
    ...

然后使用自定义取消选择逻辑修改您的测试集合:

def pytest_collection_modifyitems(items, config):
    """ deselect test items which do not match the fixture restriction """
    deselection_items = []
    for item in items:
        # There may be a better way than regex to get the parameter
        passed_param = re.search(r'\[(.+?)\]', item.name).group(1)
        restrictions = set([mark.args[0] for mark in item.iter_markers(name='restriction')])
        if len(restrictions) > 0:
            if passed_param not in restrictions:
                deselection_items.append(item)
    items[:] = [item for item in items if item not in deselection_items]
    config.hook.pytest_deselected(items=deselection_items)

我最终编写了自己的装饰器,我认为它相当简单和干净:

import functools

def skip_targets(excluded_values):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            paramA = kwargs['paramA']
            if paramA in excluded_values:
                pytest.skip('Param A "{}" currently not supported'.format(paramA))
            func(*args, **kwargs)
        return wrapper
    return decorator

要停用对 paramA 使用夹具的测试,您可以像这样排除值 X

@skip_targets(['X'])
def test_param(self, paramA):
    pass