Skip to content

Same named test functions in different Pytester tests will use the same tmp_path location #12731

Open
@StefanBRas

Description

@StefanBRas

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: pytesterrelated to the pytester builtin plugin

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions