Skip to content

Pytest classmethod fixtures with scope='class' no longer save class variables. #4949

Closed
@xNinjaKittyx

Description

@xNinjaKittyx

This might not be a bug, and it might have just been a workaround, that has been properly fixed. If it has, please let me know how to migrate to a proper write of the test.

At our work, we wrote many tests like this ever since fixtures were introduced:

class TestClass:

    @classmethod
    @pytest.fixture(scope='class', autouse=True)
    def some_setup_fixture(cls):
        print('ran fixture')
        cls.example = 'hello world'

    def test_1(self):
        print('run test')
        print(cls.example)

    def test_2(self):
        print('run test2')
        print(cls.example)

In this scenario, we want the fixture to only run once per class, but we also want to keep a context of the class.

however, starting from Pytest > 3.7.0 (and all 4 versions), this no longer works. The context is completely removed:

λ pytest -svx test.py
================================================================== test session starts ==================================================================
platform win32 -- Python 3.6.5, pytest-3.7.1, py-1.8.0, pluggy-0.9.0 -- REDACTED\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.6.5', 'Platform': 'Windows-10-10.0.14393-SP0', 'Packages': {'pytest': '3.7.1', 'py': '1.8.0', 'pluggy': '0.9.0'}, 'Plugins': {'xdist': '1.26.1', 'metadata': '1.8.0', 'json-report': '0.7.0', 'html': '1.20.0', 'forked': '1.0.2', 'cov': '2.6.1', 'asyncio': '0.10.0', 'pylama': '7.6.6'}}
rootdir: C:\Users\daniel.ahn\Documents\star, inifile:
plugins: xdist-1.26.1, metadata-1.8.0, json-report-0.7.0, html-1.20.0, forked-1.0.2, cov-2.6.1, asyncio-0.10.0, pylama-7.6.6
collected 1 item                                                                                                                                         

test.py::TestClass::test_1 ran fixture
run test
FAILED

======================================================================= FAILURES ========================================================================
___________________________________________________________________ TestClass.test_1 ____________________________________________________________________

self = <test.TestClass object at 0x000001F4A8E4C748>

    def test_1(self):
        print('run test')
>       print(self.example)
E       AttributeError: 'TestClass' object has no attribute 'example'

test.py:15: AttributeError
=============================================================== 1 failed in 0.12 seconds ================================================================

Strange that fixture runs, but whatever variables it sets, pytest doesn't seem to care.

Looking at the submitted changelog, nothing seems to stick out.

removing scope='class' and @classmethod allows us to use the fixture on the newer versions, but it'll run for every single function in the class, which is not the behavior we want.

So two questions:

  1. Is this style of writing tests unwanted? Is it invalid?
  2. If it's invalid, what is the proper right way to write these kinds of tests? Ideally would like an solution that would require minimal work.

pip list:

Package                  Version       Location
------------------------ ------------- ----------------------------------
aiofiles                 0.4.0
aiohttp                  3.5.4
alabaster                0.7.12
apipkg                   1.5
asn1crypto               0.24.0
async-timeout            3.0.1
asyncssh                 1.16.0
atomicwrites             1.3.0
attrs                    19.1.0
Babel                    2.6.0
bcrypt                   3.1.6
boto3                    1.9.111
botocore                 1.12.111
certifi                  2018.11.29
cffi                     1.12.2
chardet                  3.0.4
Click                    7.0
cmd2                     0.9.10
colorama                 0.4.1
coverage                 4.5.2
cryptography             2.6.1
decorator                4.3.2
docutils                 0.14
eradicate                1.0
execnet                  1.5.0
idna                     2.8
idna-ssl                 1.1.0
imagesize                1.1.0
ipython-genutils         0.2.0
Jinja2                   2.10
jmespath                 0.9.4
jsonschema               2.6.0
junitxml                 0.7
jupyter-core             4.4.0
limits                   1.3
MarkupSafe               1.1.0
mccabe                   0.6.1
more-itertools           6.0.0
multidict                4.5.2
mypy                     0.670
mypy-extensions          0.4.1
nbformat                 4.4.0
netmiko                  2.3.3
numpy                    1.16.2
packaging                19.0
paramiko                 2.4.2
pip                      18.1
plotly                   3.6.0
pluggy                   0.9.0
plumbum                  1.6.7
psutil                   5.6.0
py                       1.8.0
pyasn1                   0.4.5
pycodestyle              2.5.0
pycparser                2.19
pydocstyle               3.0.0
pyflakes                 2.1.1
Pygments                 2.3.1
pylama                   7.6.6
pylogbeat                1.0.2
pymongo                  3.7.2
PyNaCl                   1.3.0
pyparsing                2.3.1
pyperclip                1.7.0
pyreadline               2.1
pyserial                 3.4
pytest                   3.7.1
pytest-asyncio           0.10.0
pytest-cov               2.6.1
pytest-cover             3.0.0
pytest-coverage          0.0
pytest-forked            1.0.2
pytest-html              1.20.0
pytest-json-report       0.7.0
pytest-metadata          1.8.0
pytest-xdist             1.26.1
python-dateutil          2.8.0
python-logstash-async    1.5.0
python-rapidjson         0.7.0
pytz                     2018.9
pyvmomi                  6.7.1.2018.12
PyYAML                   3.13
pyzmq                    18.0.1
requests                 2.21.0
retrying                 1.3.3
rpyc                     4.0.2
s3transfer               0.2.0
scp                      0.13.0
setuptools               40.6.3
six                      1.12.0
snowballstemmer          1.2.1
Sphinx                   1.8.4
sphinx-autodoc-typehints 1.6.0
sphinxcontrib-websupport 1.1.0
textfsm                  0.4.1
toml                     0.10.0
traitlets                4.3.2
typed-ast                1.3.1
typing-extensions        3.7.2
urllib3                  1.24.1
wcwidth                  0.1.7
wheel                    0.32.3
xmltodict                0.12.0
xxhash                   1.3.0
yarl                     1.3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions