django - How to clean up images and temporary files created during testing

Are you stuck figuring out a sane way to clean up images and other temporary files created during testing your django app? Well, it's your lucky day!

The problem

When testing a django app, we may need to create temporary files for testing upload process, or format conversion, or thumbnail generation, etc.

But when the tests finish running, the uploaded files stay on the disk. Django doesn't provide any API to remove files uploaded/created during testing.

The (bad) solution

The simple solution is to call os.remove to delete temporary files when you're done testing from tearDown or tearDownClass method.

But this is not an efficient solution.

Why? Suppose you want to test a piece of code which generates multiple thumbnails in various sizes for an uploaded image. Obviously, you'll keep the different size thumbnails in different folders, for example, 100 x 100 thubnails in 100x100 folder, 50X50 thumbnails in 50x50 folder, and the original, full size images in a separate original folder.

Now, if you want to delete all these files, you'll need to call os.remove multiple times, with multiple file paths. And that sucks.

The better solution

Django allows overriding the settings during testing. That means, you can override the MEDIA_ROOT settings to provide a separate folder where Django will keep the uploaded files during testing. And when you're done testing, just delete the whole folder. BOOM!

Code example:

from django.test import override_settings
import shutil

TEST_DIR = 'test_data'

class SomeTests(TestCase):
    ...

    # use the `override_settings` decorator on 
    # those methods where you're uploading images

    @override_settings(MEDIA_ROOT=(TEST_DIR + '/media'))
    def test_file_upload(self):
        ...
        # your code
        ...

...


# then create a tearDownModule function
# to remove the `TEST_DIR` folder at the 
# end of tests

def tearDownModule():
    print "\nDeleting temporary files...\n"
    try:
        shutil.rmtree(TEST_DIR)
    except OSError:
        pass