如何使用外部夹具跳过 pytest?

新手上路,请多包涵

背景

我在 conftest 文件 中运行一个带有 夹具 的 py.test。您可以看到下面的代码(一切正常):

example_test.py

 import pytest

@pytest.fixture
def platform():
    return "ios"

@pytest.mark.skipif("platform == 'ios'")
def test_ios(platform):
    if platform != 'ios':
        raise Exception('not ios')

def test_android_external(platform_external):
    if platform_external != 'android':
        raise Exception('not android')

比赛.py

 import pytest

@pytest.fixture
def platform_external():
    return "android"

问题

现在我希望能够跳过一些不适用于我当前测试运行的测试。在我的示例中,我正在为 iOSAndroid 运行测试(这仅用于演示目的,可以是任何其他表达式)。

不幸的是,我无法在 skipif 语句中找到(我的 外部 定义的 夹具platform_external 。当我运行下面的代码时,我收到以下异常: NameError: name 'platform_external' is not defined 。我不知道这是否是一个 py.test 错误,因为 本地 定义的固定装置正在运行。

example_test.py 的附加组件

@pytest.mark.skipif("platform_external == 'android'")
def test_android(platform_external):
    """This test will fail as 'platform_external' is not available in the decorator.
    It is only available for the function parameter."""
    if platform_external != 'android':
        raise Exception('not android')

所以我想我会创建自己的 装饰器,只是为了确保它不会接收灯具作为参数:

 from functools import wraps

def platform_custom_decorator(func):
    @wraps(func)
    def func_wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return func_wrapper

@platform_custom_decorator
def test_android_2(platform_external):
    """This test will also fail as 'platform_external' will not be given to the
    decorator."""
    if platform_external != 'android':
        raise Exception('not android')

问题

如何在 conftest 文件中定义 夹具 并使用它(有条件地) 跳过测试

原文由 Marco Pashkov 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 541
2 个回答

似乎 py.test 在评估 skipif 的表达式时不使用测试装置。 By your example, test_ios is actually successful because it is comparing the function platform found in the module’s namespace to the "ios" string, which evaluates to False 因此测试被执行并成功。如果 pytest 如您所料插入用于评估的夹具,则应该跳过该测试。

解决您的问题(虽然不是您的问题)的方法是实施一个检查测试标记的装置,并相应地跳过它们:

 # conftest.py
import pytest

@pytest.fixture
def platform():
    return "ios"

@pytest.fixture(autouse=True)
def skip_by_platform(request, platform):
    if request.node.get_closest_marker('skip_platform'):
        if request.node.get_closest_marker('skip_platform').args[0] == platform:
            pytest.skip('skipped on this platform: {}'.format(platform))

一个关键点是 autouse 参数,这将使该夹具自动包含在所有测试中。然后你的测试可以像这样标记要跳过的平台:

 @pytest.mark.skip_platform('ios')
def test_ios(platform, request):
    assert 0, 'should be skipped'

原文由 Bruno Oliveira 发布,翻译遵循 CC BY-SA 4.0 许可协议

Bruno Oliveira 的解决方案正在运行,但对于新的 pytest (>= 3.5.0),您需要添加 pytest_configure:


# conftest.py
import pytest

@pytest.fixture
def platform():
    return "ios"

@pytest.fixture(autouse=True)
def skip_by_platform(request, platform):
    if request.node.get_closest_marker('skip_platform'):
        if request.node.get_closest_marker('skip_platform').args[0] == platform:
            pytest.skip('skipped on this platform: {}'.format(platform))

def pytest_configure(config):
  config.addinivalue_line(
        "markers", "skip_by_platform(platform): skip test for the given search engine",
  )

利用:

 @pytest.mark.skip_platform('ios')
def test_ios(platform, request):
    assert 0, 'should be skipped'

原文由 user1921483 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题