Pytest: resolve manually set basetemp to a absolute path

Created on 20 Nov 2018  路  7Comments  路  Source: pytest-dev/pytest

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 ```

  • [X] Include a detailed description of the bug or suggestion
  • [X] pip list of the virtual environment you are using:
  • [X] pytest and operating system versions:
  • [X] Minimal example if possible - already in the text
tmpdir bug

Most helpful comment

Just to add that you can use monkeypatch.chdir to change directories safely inside tests.

All 7 comments

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.

Was this page helpful?
0 / 5 - 0 ratings