简体   繁体   English

根据使用的夹具添加 pytest 标记进行测试

[英]Adding pytest markers to test depending on used fixtures

I am looking for a way to mark pytest tests with markers depending on which fixtures this test uses.我正在寻找一种方法来使用标记标记 pytest 测试,具体取决于该测试使用的固定装置。

I would like to use this to filter tests based on the features they use.我想用它来根据他们使用的功能过滤测试。 For example: A test that uses the "database_connection" fixture should automatically be marked with "database".例如:使用“database_connection”fixture 的测试应该自动标记为“database”。 This way I could include or exclude all such tests based on whether or not the database credentials are at hand.这样,我可以根据是否有数据库凭据来包含或排除所有此类测试。

This is what I currently have:这是我目前拥有的:

def pytest_configure(config):
    """Register hook to extend the list of available markers."""
    config.addinivalue_line("markers", "database: mark test that need a database connection.")

def pytest_collection_modifyitems(config, items):  # pylint: disable=unused-argument
    """Register hook to map used fixtures to markers."""
    for item in items:
        if "database_connection" in item.fixturenames:
            database_marker = pytest.mark.database()
            item.add_marker(database_marker)

@pytest.fixture
def database_connection():
    """Fixture providing a database connection."""

This works just the way I want but I dislike having to maintain the mapping from fixture to mark separated from the fixture itself.这正是我想要的方式,但我不喜欢必须维护从夹具到标记的映射与夹具本身分开。 What I'd like to do is decorate the fixtures with the markers that should be set on all tests that use them.我想做的是用应该在所有使用它们的测试上设置的标记来装饰灯具。 It should look like this:它应该如下所示:

def pytest_configure(config):
    """Register hook to extend the list of available markers."""
    config.addinivalue_line("markers", "database: mark test that need a database connection.")

def pytest_collection_modifyitems(config, items):  # pylint: disable=unused-argument
    """Register hook to map used fixtures to markers."""
    for item in items:
        for fixture in item.fixtures:
            item.add_markers(fixture.markers)         

@pytest.fixture(markers=["database"])
def database_connection():
    """Fixture providing a database connection."""

Of course I could build a decorator that stores the mapping in a global variable:当然,我可以构建一个将映射存储在全局变量中的装饰器:

_fixture_marker_map = {}

def set_markers(*markers):
    def decorator_set_markers(func):
        _fixture_marker_map[func.__name__] = markers
        
        @functools.wraps(func)
        def wrapper_set_markers(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper_set_markers
    return decorator_set_markers

@set_markers("database")
@pytest.fixture
def database_connection():
    """Fixture providing a database connection."""

However, this feels a bit hacky.但是,这感觉有点hacky。 I'm pretty sure this is not an odd usecase and there might be some pytest feature that already provides what I need.我很确定这不是一个奇怪的用例,可能有一些 pytest 功能已经提供了我需要的东西。

Does anyone have an idea how to implement this in a simple manner?有谁知道如何以简单的方式实现这一点?

There's a simple solution that seems to work.有一个简单的解决方案似乎有效。 The trick is to notice that you can parametrize fixtures and mark the parameters.诀窍是注意您可以参数化夹具并标记参数。 You can just ignore the parameter.您可以忽略该参数。 For example:例如:

@pytest.fixture(params=[pytest.param(None, marks=pytest.mark.db))
def database_connection(request):
    """Fixture providing a database connection."""
    ...


def test_db_connection(database_connection):
    ...

will automatically mark any test that consumes the database_connection with the db mark.将使用db标记自动标记任何使用database_connection的测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM