Pytest: markers stains on all related classes

Created on 23 Aug 2014  路  14Comments  路  Source: pytest-dev/pytest

Originally reported by: Markus Unterwaditzer (BitBucket: untitaker, GitHub: untitaker)


Given this class hierarchy:

import pytest

class Foo(object):
    def test_lol(self):
        pass

@pytest.mark.skipif(False, reason='BECAUSE')
class TestBar(Foo):
    pass

@pytest.mark.skipif(True, reason='BECAUSE')
class TestBaz(Foo):
    pass

py.test will skip the single testcase of both TestBar and TestBaz.


collection marks bug

Most helpful comment

Here's a ugly workaround:


def mark_class(marker):
    '''Workaround for https://github.com/pytest-dev/pytest/issues/568'''
    import types
    def copy_func(f):
        try:
            return types.FunctionType(f.__code__, f.__globals__,
                                      name=f.__name__, argdefs=f.__defaults__,
                                      closure=f.__closure__)
        except AttributeError:
            return types.FunctionType(f.func_code, f.func_globals,
                                      name=f.func_name,
                                      argdefs=f.func_defaults,
                                      closure=f.func_closure)

    def mark(cls):
        for method in dir(cls):
            if method.startswith('test_'):
                f = copy_func(getattr(cls, method))
                setattr(cls, method, marker(f))
        return cls
    return mark


import pytest

class Foo(object):
    def test_lol(self):
        pass

@mark_class(pytest.mark.skipif(False, reason='BECAUSE'))
class TestBar(Foo):
    pass

@mark_class(pytest.mark.skipif(True, reason='BECAUSE'))
class TestBaz(Foo):
    pass

All 14 comments

@untitaker this relates to a recent issue wrt marker transfer, current consent is that class level markers move to inherited methods

Relates to #535

Yeah I think this is a duplicate.

Ronny, I don't understand what you're saying. Are class markers discouraged? Is this expected behavior?

On 25 July 2015 19:16:40 CEST, Brianna Laugher [email protected] wrote:

Relates to #535


Reply to this email directly or view it on GitHub:
https://github.com/pytest-dev/pytest/issues/568#issuecomment-124863023

Sent from my phone. Please excuse my brevity.

Here's the PR: #848

@untitaker py.test has a bug wrt marker transfer, we are on it

Ok, thanks!

On 26 July 2015 09:00:22 CEST, Ronny Pfannschmidt [email protected] wrote:

@untitaker py.test has a bug wrt marker transfer, we are on it


Reply to this email directly or view it on GitHub:
https://github.com/pytest-dev/pytest/issues/568#issuecomment-124951806

Sent from my phone. Please excuse my brevity.

Any update on this issue?

Unfortunately not, a backward compatible resolution is hard and needs time

Here's a ugly workaround:


def mark_class(marker):
    '''Workaround for https://github.com/pytest-dev/pytest/issues/568'''
    import types
    def copy_func(f):
        try:
            return types.FunctionType(f.__code__, f.__globals__,
                                      name=f.__name__, argdefs=f.__defaults__,
                                      closure=f.__closure__)
        except AttributeError:
            return types.FunctionType(f.func_code, f.func_globals,
                                      name=f.func_name,
                                      argdefs=f.func_defaults,
                                      closure=f.func_closure)

    def mark(cls):
        for method in dir(cls):
            if method.startswith('test_'):
                f = copy_func(getattr(cls, method))
                setattr(cls, method, marker(f))
        return cls
    return mark


import pytest

class Foo(object):
    def test_lol(self):
        pass

@mark_class(pytest.mark.skipif(False, reason='BECAUSE'))
class TestBar(Foo):
    pass

@mark_class(pytest.mark.skipif(True, reason='BECAUSE'))
class TestBaz(Foo):
    pass

Here's how PyKafka works around this issue in its test suite

@emmett9001 there is a pending branch for the initial mark refactor in #1534

after it is merged the base for a backward compatible implementation of non-smearing marker combinations wil lbe in place

Since we have #1670 to track all marker staining related issues and the fix for that unfortunately won't make it to 3.0, I'm removing the milestone for now.

I've tried the workaround posted by @untitaker and it works like a charm. Thanks @untitaker!

fixed in #3317

Was this page helpful?
0 / 5 - 0 ratings