Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom marker kwargs for test case method is overwritten from class marker. #2515

Closed
petr-balogh opened this issue Jun 21, 2017 · 5 comments
Closed
Labels
topic: marks related to marks, either the general marks or builtin

Comments

@petr-balogh
Copy link

petr-balogh commented Jun 21, 2017

Custom marker decorator for class is not overwritten by marker from method.

Content of test_file.py

import pytest

glob = pytest.mark.glob


@glob("class", tier=3)
class ParentClass(object):
    __test__ = False
    baseclass_atr = "baseclass"


@glob("class", tier=2)
class TestClass(ParentClass):
    __test__ = True
    @glob("method", scope="method", tier=1)
    def test_demo1(self):
        print "Info test 1"

content of conftest.py

def pytest_collection_modifyitems(session, config, items):
    for item in items:
        g = item.get_marker("glob")
        print ("Marker is %s" % g)
        if g is not None:
            for info in g:
                print ("Glob args: %s, kwargs: %s" % (info.args, info.kwargs))

Output of pytest:

py.test --capture=no ./test_file.py 
================================================ test session starts ================================================
platform linux2 -- Python 2.7.11, pytest-3.1.3.dev22+g8c3c430, py-1.4.34, pluggy-0.4.0
rootdir: ~/sandbox/pytest/pytest_issue, inifile:
plugins: timeout-1.2.0
collected 1 item s
Marker is <MarkInfo Mark(name='glob', args=('method', 'class', 'class'), kwargs={'tier': 2, 'scope': 'method'})>
Glob args: ('method',), kwargs: {'tier': 1, 'scope': 'method'}
Glob args: ('class',), kwargs: {'tier': 3}
Glob args: ('class',), kwargs: {'tier': 2}

test_file.py Info test 1

expected Results:

Marker is <MarkInfo Mark(name='glob', args=('method', 'class', 'class'), kwargs={'tier': 1, 'scope': 'method'})>

I tried find the way, how get information if marker comes from method or class, but didn't find anything.
I was able to do solution here: petr-balogh@a0208af but in this case, you have to specify scope='method' for that marker. Any idea how to solve this issue, or make it better? Or are you OK with this patch and can I send PR?

@petr-balogh petr-balogh changed the title Custom marker wkargs for test case method is overwritten from class marker. Custom marker kwargs for test case method is overwritten from class marker. Jun 21, 2017
@RonnyPfannschmidt RonnyPfannschmidt added the topic: marks related to marks, either the general marks or builtin label Jun 21, 2017
@RonnyPfannschmidt
Copy link
Member

that api for the combined maks gives a legacy view and it should be avoided, deprecation warnings will be added in the next major release for using combined marks

making them more complex while adding a new completely backward incompatilbe "slurp" of a parameter cant be done

@RonnyPfannschmidt
Copy link
Member

btw- for getting elemental mark objects, please take a look at https://github.com/petr-balogh/pytest/blob/a0208afa37a3f53cf60446d27348a01020b069df/_pytest/mark.py#L373 - the mark-info class also contains all non-recombined marks

@RonnyPfannschmidt
Copy link
Member

actually, after seeingthe code trough i will have to close this issue as invalid

mark-info objects on functions containing merged args/kwargs is a legacy behavior that cant be removed without breaking testsuites

there will be a replacement api for marks - in future

@petr-balogh
Copy link
Author

Hi @RonnyPfannschmidt I see that mark-info class contains all non-recombined marks, that what I was printing in output of example. But I didn't find way how to distinguish which one is defined from class and which one is from method (I mean if I won't put arg "class" or "method" as I did in example).

We moved from unittest some time ago, and we used to have all tests marked with specific tier
For example we have tests which we mark with tier marker, and then we would like to collect only tests which are marked with @attr(tier=1). What is problem, that we have some classes which are marked for example with @attr(tier=1) and then all test cases (methods inside that class) are marked with tier = 1 , but we want also allow to overwrite some test inside that class to be tier = 2 for example. But it's not possible.

I thought also about create markers like tese :

tier1 = pytest.mark.tier1
tier2 = pytest.mark.tier2

but problem is that if you will have class like here:

@tier1
class TestClass(object):
    @tier2
    def test_demo1(self):
        print "Info test 1"

    def test_demo2(self):
        print "Info test 1"

In this example you can run with pytest with parameter -m tier1, but in this case both of tests cases: test_demo1 and test_demo2 will be executed, but I would like run only tests which are really tier1.

Could you please advise how to solve this issue?

@RonnyPfannschmidt
Copy link
Member

@petr-balogh currently there is no solution for this as this is a very long standing tructureal issue in pytest

in the last few years i threw in weeks of development time to fine a solution, by now there is a path to progression but noting wokrable yet

however your isuse just gave me an idea on how to provide a usefull solution ot the issue for the next pytest major release

we can expose pristine non-transferred marks as function.pytestmark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: marks related to marks, either the general marks or builtin
Projects
None yet
Development

No branches or pull requests

2 participants