pytest-dev / pytest-dev/pytest
Same named test functions in different `Pytester` tests will use the same `tmp_path` location
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 14.5k
- Forks
- 3.4k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 35
Description
If you setup Pytester tests that uses tmp_path then they will share directory if named the same, even if run in different tests. This only happens when run with runpytest not inline_run. So when running this code:
def test_1(pytester: Pytester):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
pytester.runpytest()
def test_2(pytester: Pytester):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
pytester.runpytest()
both inner test functions will have tmp_path pointing to the same directory.
This might not be a bug outright since I don't think pytester makes any claim for this not to happen, but I think it's a major footgun for using pytester.
Below is a full reproduction that shows the paths are indeed the same in the given situations. When this is run, the fixture will throw an error for TestRunPytest
from pytest import Pytester
import pytest
import re
@pytest.fixture(scope="class")
def extract_and_compare_temp_path():
paths = []
def _saver(lines):
for line in lines:
if match := re.match(r"tmp_path = PosixPath.'(.*)'.", line):
paths.append(match.group(1))
yield _saver
# The paths should not be the same
assert paths[0] != paths[1]
class TestRunPytest: # both test functions uses the same test path
def test_1(self, pytester: Pytester, extract_and_compare_temp_path):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
path = pytester.runpytest().outlines
extract_and_compare_temp_path(path)
def test_2(self, pytester: Pytester, extract_and_compare_temp_path):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
path = pytester.runpytest().outlines
extract_and_compare_temp_path(path)
class TestRunPytestDifferentFunctionNames: # does not same tmp_path
def test_1(self, pytester: Pytester, extract_and_compare_temp_path):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
path = pytester.runpytest().outlines
extract_and_compare_temp_path(path)
def test_2(self, pytester: Pytester, extract_and_compare_temp_path):
pytester.makepyfile(
"""
def test_with_other_name(tmp_path):
assert False
"""
)
path = pytester.runpytest().outlines
extract_and_compare_temp_path(path)
class TestInlineRun: # These have the different temp paths
def test_1(self, pytester: Pytester, extract_and_compare_temp_path):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
path = pytester.inline_run().getfailures()[0]
extract_and_compare_temp_path([path.longreprtext])
def test_2(self, pytester: Pytester, extract_and_compare_temp_path):
pytester.makepyfile(
"""
def test(tmp_path):
assert False
"""
)
path = pytester.inline_run().getfailures()[0]
extract_and_compare_temp_path([path.longreprtext])
Env: platform linux -- Python 3.12.5, pytest-8.3.2, pluggy-1.5.0
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Pytester behavior exercised by the reported runpytest reproduction, and compare it with inline_run, which already produces different paths. Trace how the inner test name contributes to tmp_path allocation. Done means same-named inner tests invoked through separate runpytest calls receive distinct tmp_path locations, with a regression test covering the reproduction.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100