Pytest: apply markers based on fixtures/dependent fixtures

Created on 9 Feb 2016  路  6Comments  路  Source: pytest-dev/pytest

use case is deselecting tests based on markers that relate to used fixtures

collection marks enhancement feature-branch proposal

Most helpful comment

Hi,

I came to the point in my project, where I want to use (custom) marks on fixtures. I read thought the documentation and I found that marks can only be applied to tests and have no effect on fixtures. Then I found this issue which I suppose is actually related to the problem that I'm struggling with.

I actually found a workaround for this issue. It turns out that this "feature" is already implemented as a side effect of pytest.param() because you can define fixture with single parameter and assign marks to that parameter. This basically creates fixture with marks applied to it.

import pytest

# The value of fixture param does not matter, we only use params to pass marks to fixture
@pytest.fixture(params=[pytest.param(0, marks=pytest.mark.local_address)])
def address():
    return '127.0.0.1', 7000

The above code could be treated as equal to below fixture definition.

import pytest

@pytest.fixture
@pytest.mark.local_address
def address():
    return '127.0.0.1', 7000

Now when we define below test case

def test(address):
    pass

Running pytest -m local_address will get us following outcome:

1 passed in 0.03 seconds

Running pytest -m "not local_address"

1 deselected in 0.01 seconds

You can also use marks like skip or xfail and chaining fixtures also works and keeps the information about marks. So my question is: is this actually intended? If yes, can be make it to work with the definition in second code snippet which could basically assume that fixture without params defined is a single param fixture with marks applied to it?

All 6 comments

Can't this easily be done already?

def pytest_collection_modifyitems(items):
    for item in items:
        if 'qapp' in getattr(item, 'fixturenames', ()):
            item.add_marker('gui')

@The-Compiler the markers are supposed to be taken from the actual fixture function, thats potentially a indirect dependency

Hi,

I came to the point in my project, where I want to use (custom) marks on fixtures. I read thought the documentation and I found that marks can only be applied to tests and have no effect on fixtures. Then I found this issue which I suppose is actually related to the problem that I'm struggling with.

I actually found a workaround for this issue. It turns out that this "feature" is already implemented as a side effect of pytest.param() because you can define fixture with single parameter and assign marks to that parameter. This basically creates fixture with marks applied to it.

import pytest

# The value of fixture param does not matter, we only use params to pass marks to fixture
@pytest.fixture(params=[pytest.param(0, marks=pytest.mark.local_address)])
def address():
    return '127.0.0.1', 7000

The above code could be treated as equal to below fixture definition.

import pytest

@pytest.fixture
@pytest.mark.local_address
def address():
    return '127.0.0.1', 7000

Now when we define below test case

def test(address):
    pass

Running pytest -m local_address will get us following outcome:

1 passed in 0.03 seconds

Running pytest -m "not local_address"

1 deselected in 0.01 seconds

You can also use marks like skip or xfail and chaining fixtures also works and keeps the information about marks. So my question is: is this actually intended? If yes, can be make it to work with the definition in second code snippet which could basically assume that fixture without params defined is a single param fixture with marks applied to it?

Oh that's interesting. I would like to know @RonnyPfannschmidt's opinion here, but I would like to see marks working on fixtures; seems natural and what users expect.

@nicoddemus if getfixturevalue is explicitly excluded as mark source, it can be reasonably done

that specification needs to ensure a awareness of lazy/delayed fixtures
special care needs to be taken for fixtures that override old values vs fixtures that replace other fixtures
(it may be necessary to have fixtures declare replacement vs extension more explicitly)

i will take a deeper look in a few months when i'm back to active

Great, thanks @RonnyPfannschmidt for the follow up

Was this page helpful?
0 / 5 - 0 ratings