Search code examples
pythondjangounit-testingpython-unittestfactory-boy

Django/unittest run command at the end of the test runner


I'm using the Django test runner to run my unit tests. Some of these tests use factories which create TONS of files on my local system. They all have a detectable name, and can be removed reasonably easily.

I'm trying to avoid having to either

  1. Keep a file-deleting cron job running
  2. Change my custom image model's code to delete the file if it detects that we're testing. Instead, I'd like to have a command run once (and only once) at the end of the test run to clean up all files that the tests have generated.

I wrote a small management command that deletes the files that match the intended convention. Is there a way to have the test runner run call_command on that upon completion of the entire test suite (and not just in the tearDown or tearDownClass methods of a particular test)?


Solution

  • So what we ended up doing was creating a custom test runner by adding the following line to settings.py:

    TEST_RUNNER = 'myapp.test_runner.MyTestRunner'
    

    Then in the test runner, we delete the images from within the "teardown_test_environment" method of a test runner that inherits from our existing juno test runner.

    import os                                                                                  
    import shutil
    
    from django.conf import settings
    from junorunner.testrunner import TestSuiteRunner
    
    
    class MyTestRunner(TestSuiteRunner):
    
        def teardown_test_environment(self, *args, **kwargs):
            # Remove test-created media files
            if all([
                os.path.isdir(settings.MEDIA_ROOT),
                'test' in settings.MEDIA_ROOT,
            ]):
                shutil.rmtree(settings.MEDIA_ROOT)
            super(MyTestRunner, self).teardown_test_environment(*args, **kwargs)
    

    This method is called upon teardown of the test method, and seems to be a good place to ensure that it gets called once at the end, and only once.