In tests: `MEDIA_ROOT=TemporaryDirectory()` ?

Dear group,

we’re developing an application that uses Python’s core I/O functions to access the MEDIA_ROOT directory.

A problem is that during tests, MEDIA_ROOT is the same as defined in settings.py and we would much prefer to point it to a temporary directory, that is, do something like MEDIA_ROOT=TemporaryDirectory().

The straightforward approach that is suggested in this Stack Overflow answer doesn’t work well,
because it relies on the temporary directory being implicitly cleaned up (ResourceWarning: Implicitly cleaning up <TemporaryDirectory '/tmp/…'>).

I’ve also found #23251 (Use a temporary folder to store uploaded files during tests) – Django, but the focus there seemed to have shifted from MEDIA_ROOT to STORAGES.

The best solution I’ve come up with so far is:

from pathlib import Path
from tempfile import TemporaryDirectory

from django.conf import settings
from django.test import TestCase, override_settings


class TempDirTest(TestCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        # Have both the temporary directory and the settings change
        # covered in a context.
        cls.temp_dir = Path(cls.enterClassContext(TemporaryDirectory()))
        cls.enterClassContext(override_settings(MEDIA_ROOT=cls.temp_dir))

    def test_example(self):
        print(settings.MEDIA_ROOT)
        ...

This seems to work well, but it took quite a bit of digging to arrive at it. There are many articles about the same problem, but they all seem to be either cumbersome (like mine above feels as well) or come with suble problems like in the above S/O answer.

Therefore my questions:

Best regards,
Carsten

I’m afraid I don’t understand the issue with your first suggestion (I don’t know what being implicitly cleaned up means, and why that is good or bad), but I’ve been doing this and it seems to work for my purposes:

import tempfile
from pathlib import Path
from django.test import TestCase, override_settings

@override_settings(MEDIA_ROOT=Path(tempfile.mkdtemp()))
class MyTestCase(TestCase):
    

Hello,

If you use tempfile.mkdtemp() there is no problem, because there is no cleanup. From tempfile — Generate temporary files and directories — Python 3.13.7 documentation :

mkstemp() and mkdtemp() are lower-level functions which require manual cleanup.

If you change the code to have the temporary directory cleaned up automatically:

import tempfile
from pathlib import Path
from django.test import TestCase, override_settings

@override_settings(MEDIA_ROOT=Path(tempfile.TemporaryDirectory().name))
class MyTestCase(TestCase):
    ...

and run the tests with warnings enabled (python -Wa manage.py test …):

.../python3.12/tempfile.py:940: ResourceWarning: Implicitly cleaning up <TemporaryDirectory '/tmp/testorb0vojs'>
  _warnings.warn(warn_message, ResourceWarning)
Found 7 test(s).
…
OK

But I agree that on systems where /tmp/ is cleaned automatically anyways, using mkdtemp() is an appealing option.