erez
erez

Reputation: 419

python pytest - How can I get a test markers inside its fixture methods?

I have test in pytest and added some markers such as: '@pytest.mark.xfail', the test have several fixture methods. How can I get all the markers of certain test using a fixture method?

Upvotes: 3

Views: 6402

Answers (2)

MrBean Bremen
MrBean Bremen

Reputation: 16815

The markers can be taken from the fixture request node attribute using iter_markers, as can be seen in this (nonsensical) example:

import pytest


@pytest.fixture
def get_marks(request):
    marks = [m.name for m in request.node.iter_markers()]
    if request.node.parent:
        marks += [m.name for m in request.node.parent.iter_markers()]
    yield marks


@pytest.mark.parametrize('number', [1, 2, 3])
@pytest.mark.foo
@pytest.mark.xfail
def test_marks(get_marks, number):
    print(get_marks)
    assert 'xfail' in get_marks
    assert number == 42

This gives the output:

...
xfail                                      [100%]['parametrize', 'xfail', 'foo']

get_marks = ['parametrize', 'xfail', 'foo'], number = 3

    @pytest.mark.parametrize('number', [1, 2, 3])
    @pytest.mark.foo
    @pytest.mark.xfail
    def test_marks(get_marks, number):
        print(get_marks)
        assert 'xfail' in get_marks
>       assert number == 42
E       assert 3 == 42

Update: Use the correct public call to get the markers as proposed by @hoefling.

Upvotes: 6

Chanda Korat
Chanda Korat

Reputation: 2561

One method is already described by @MrBean, here's one another approach using pytest_runtest_setup in conftest.py. By combiantion of global variable and pytest_runtest_setup which is pytest's own method, you can get current test marker.

This approach would give you markers of both class level and function level.

conftest.py

import pytest

marker_name = [] #Global variable so you can use it everywhere

def pytest_runtest_setup(item):
    global marker_name
    marker_name.clear() #If you would not clear this, it would append every test's marker, test by test. 
    for mark in item.iter_markers():
        marker_name.append(mark.name)


@pytest.fixture(scope='function', autouse=True) #Note here, autouse=true.
def my_fixture(request):
    request.instance.test_marker=marker_name #assign it to request's session so you can use it in other fixture and in tests as well

@pytest.fixture
def some_other_fixture(request):
    test_marker=request.instance.test_marker #access marker in fixture

test_file.py (Access that marker variable inside test using request.instance.test_marker.)

import pytest


@pytest.mark.class_marker
class TestClass:
    @pytest.mark.my_test
    @pytest.mark.xfail
    def test_foo(self,request):
        print(request.instance.test_marker) #output :  ['xfail', 'my_test', 'class_marker']

    @pytest.mark.my_test_two
    @pytest.mark.xfail
    def test_foo_two(self,request):
        print(request.instance.test_marker) #output :  ['xfail', 'my_test_two', 'class_marker']

Hope it would help !!

Upvotes: 1

Related Questions