Hi Guys,
We're experiencing some issues with new tmpdir implementation using pathlib. Starting from pytest 3.9.0 our tests started to fail.
We are using test class and a pre_process fixture, which prepares some data for the other tests within the class. In the test methods we're using the pre_process fixture (to access the data) as well as the tmpdir pytest builtin fixture to store some outcomes of the tests. Minimal failing example is pasted below:
import pytest, os
class TestDummy():
@pytest.fixture(scope="class")
def pre_process(self, tmpdir_factory):
path_with_data = tmpdir_factory.mktemp('data')
return path_with_data
@pytest.mark.parametrize("param", range(2))
def test_dummy(self, tmpdir, pre_process, param):
os.chdir(pre_process)
# further processing
def test_dummy2(self, tmpdir, pre_process):
os.chdir(pre_process)
# further processing
Because of the directory change in test_dummy, next invocation of the tests fail due to pathlib error, as below:
```____________________________________________________________________________________________________ ERROR at setup of TestDummy.test_dummy[1] _____________________________________________________________________________________________________
self = PosixPath('tmp')
def iterdir(self):
"""Iterate over the files in this directory. Does not yield any
result for the special paths '.' and '..'.
"""
if self._closed:
self._raise_closed()
for name in self._accessor.listdir(self):
../../../.pyenv/versions/3.6.5/lib/python3.6/pathlib.py:1079:
pathobj = PosixPath('tmp'), args = ()
@functools.wraps(strfunc)
def wrapped(pathobj, *args):
return strfunc(str(pathobj), *args)E FileNotFoundError: [Errno 2] No such file or directory: 'tmp'
../../../.pyenv/versions/3.6.5/lib/python3.6/pathlib.py:387: FileNotFoundError
and in fact we end up with 1 pass and 2 errors in this particular case.
We currently have workaround for this issue (store the cwd before changing it and restore it before the test end), but I'd like to ask you if this is how it should behave? I'd expect that state of one test does not influence the other test's state.
The issue is observable if no class hierarchy is used as well.
Another workaround (a little bit nasty) is to reset internal pytest variable in pre_process macro:
```@pytest.fixture(scope="module")
def pre_process(tmpdir_factory):
path_with_data = tmpdir_factory.mktemp('data')
tmpdir_factory._tmppath_factory._basetemp = None
return path_with_data```
Environment details:
Python 3.6.5 (via pyenv), 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:37:27 UTC 2018 i686 i686 i686 GNU/Linux
$ pip list
Package Version
atomicwrites 1.2.1
attrs 18.2.0
more-itertools 4.3.0
pip 18.1
pluggy 0.8.0
py 1.7.0
pytest 4.0.0
setuptools 40.6.2
six 1.11.0 ```
pip list of the virtual environment you are using:please paste the full traceback, the cut version lacks the context needed to get any idea whats happening
Sure:
$ pytest test.py
=============================================================================================================== test session starts ================================================================================================================
platform linux -- Python 3.6.5, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/mrusi, inifile: pytest.ini
collected 3 items
test.py .EE [100%]
====================================================================================================================== ERRORS ======================================================================================================================
____________________________________________________________________________________________________ ERROR at setup of TestDummy.test_dummy[1] _____________________________________________________________________________________________________
self = PosixPath('tmp')
def iterdir(self):
"""Iterate over the files in this directory. Does not yield any
result for the special paths '.' and '..'.
"""
if self._closed:
self._raise_closed()
> for name in self._accessor.listdir(self):
../../../.pyenv/versions/3.6.5/lib/python3.6/pathlib.py:1079:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pathobj = PosixPath('tmp'), args = ()
@functools.wraps(strfunc)
def wrapped(pathobj, *args):
> return strfunc(str(pathobj), *args)
E FileNotFoundError: [Errno 2] No such file or directory: 'tmp'
../../../.pyenv/versions/3.6.5/lib/python3.6/pathlib.py:387: FileNotFoundError
_____________________________________________________________________________________________________ ERROR at setup of TestDummy.test_dummy2 ______________________________________________________________________________________________________
self = PosixPath('tmp')
def iterdir(self):
"""Iterate over the files in this directory. Does not yield any
result for the special paths '.' and '..'.
"""
if self._closed:
self._raise_closed()
> for name in self._accessor.listdir(self):
../../../.pyenv/versions/3.6.5/lib/python3.6/pathlib.py:1079:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pathobj = PosixPath('tmp'), args = ()
@functools.wraps(strfunc)
def wrapped(pathobj, *args):
> return strfunc(str(pathobj), *args)
E FileNotFoundError: [Errno 2] No such file or directory: 'tmp'
../../../.pyenv/versions/3.6.5/lib/python3.6/pathlib.py:387: FileNotFoundError
================================================================================================================= warnings summary =================================================================================================================
/home/mrusi/.pyenv/versions/3.6.5/lib/python3.6/site-packages/_pytest/resultlog.py:39
/home/mrusi/.pyenv/versions/3.6.5/lib/python3.6/site-packages/_pytest/resultlog.py:39: RemovedInPytest4Warning: --result-log is deprecated and scheduled for removal in pytest 4.0.
See https://docs.pytest.org/en/latest/usage.html#creating-resultlog-format-files for more information.
_issue_config_warning(RESULT_LOG, config)
-- Docs: https://docs.pytest.org/en/latest/warnings.html
================================================================================================== 1 passed, 1 warnings, 2 error in 0.09 seconds ===================================================================================================
it seems the normal output is not enough (this is a case where pytest removing pytest from the traceback actually makes things worse)
please take a look if the traceback given by pytest test.py --fulltrace gives more insight
also a sidenote - i'm testing with pytest 4 myself and i don't see an issue on my system, so we might be looking at a environmental/hard to replicate issue
since the "temporary directory" that seems to be used in your example is a relative path, i do wonder if it might be a miss-configured environment and if/how we should warn
Sorry for a confusion! I was using custom config in pytest.ini, setting the basetemp to relative path, like this: pytest --basetemp=./tmp test.py
Full stack trace below:
full_trace.txt
i see - that's a unintended behavior difference then and must be resolved by making the temporary folder absolute
the new code doesn't resolve the path to its final absolute value - and it should
thanks for reporting
Just to add that you can use monkeypatch.chdir to change directories safely inside tests.
Most helpful comment
Just to add that you can use
monkeypatch.chdirto change directories safely inside tests.