Isolate and Debug File Side-Effects with Pytest tmp_path

One of the fixtures that Pytest offers is tmp_path that it describes as having the following behavior:

"Return a temporary directory (as pathlib.Path object) which is unique to each test function invocation."

It can be used to provide a unique, deterministic, isolated temporary directory for file operations a program needs to perform while being tested.

For example, my py-vmt CLI needs to access and write files in the user's config and data dirs. Under test, I need to monkeypatch that behavior to point to a tmp_path where the tests can operate without clobbering one another or non-test uses of the CLI.

# auto fixture for all test cases that monkeypatches the platform dirs to a tmp
# path so that test side-effects don't persist between runs
@pytest.fixture(autouse=True)
def use_tmp_platform_dirs(tmp_path, monkeypatch):
    data_dir = tmp_path / "data"
    config_dir = tmp_path / "config"
    data_dir.mkdir()
    config_dir.mkdir()
    monkeypatch.setattr(CliContext, "get_data_dir", staticmethod(lambda: data_dir))
    monkeypatch.setattr(CliContext, "get_config_dir", staticmethod(lambda: config_dir))

What's particularly neat about this is that Pytest has a unique and deterministic location for tmp_path for each run and unit test. It also has a retention policy of 3, which means I can always go back and look at the state of those directories for the last three runs of the test suite.

The docs describe the per-run and per-test directory structure of this tmp_path as:

{temproot}/pytest-of-{user}/pytest-{num}/{testname}/

where temproot can be found with tempfile.gettempdir().

>>> import tempfile
>>> tempfile.gettempdir()
'/var/folders/zc/q6gnvbgx6kq77828jn38716r0000gn/T'

Now that I have that directory location, I can start poking around at the rest of the path values. Eventually I drill down enough to access the data directory for one of those test cases.

 ls /var/folders/zc/q6gnvbgx6kq77828jn38716r0000gn/T/pytest-of-lastword/pytest-2
test_no_status0                    test_start_at_past_timecurrent     test_start_status_stop_flow0
test_no_statuscurrent              test_start_cancel_flow0            test_start_status_stop_flowcurrent
test_start_at_past_time0           test_start_cancel_flowcurrent

 ls /var/folders/zc/q6gnvbgx6kq77828jn38716r0000gn/T/pytest-of-lastword/pytest-2/test_start_status_stop_flow0
config data

 cat /var/folders/zc/q6gnvbgx6kq77828jn38716r0000gn/T/pytest-of-lastword/pytest-2/test_start_status_stop_flow0/data/session_log.json
[{"end_time": "2026-03-14T16:35:11+00:00", "project_name": "my-project", "start_time": "2026-03-14T15:05:11+00:00"}]

This provides an additional place to look when debugging some unexpected behavior because I can peek at the final state of those files. Maybe there is a clue in there about what went wrong during a specific test failure.

If you want to see a full example of using tmp_path in this way, check out this test_cli.py file for the py-vmt repo.

Tell us about your project

We build good software through good partnerships. Reach out and we can discuss your business, your goals, and how VisualMode can help.