Nurzhan Nogerbek
Nurzhan Nogerbek

Reputation: 5236

How delete image files after unit test finished?

In unit test I create 3 objects (articles) at the beginning. After test complete I notice that there are 3 images in media_root folder.

Question: How to delete that images which was created after test finished?

P.S. I tried to use next code but it delete media_root folder.

def tearDown(self):
        rmtree(settings.MEDIA_ROOT, ignore_errors=True)

NOTE: Problems in methods test_article_form_valid and test_article_crud.

tests.py:

class ArticleTestCase(TestCase):
    def setUp(self):  
        self.image = open(os.path.join(BASE_DIR, 'static/images/tests/image.jpg'), "r")

    def test_article_form_valid(self):
        data = {
            'head': 'TEXT',
        }
        files_data = {
            'image': SimpleUploadedFile(
                name=self.image.name,
                content=self.image.read(),
                content_type='image/jpeg'
            )
        }
        form = ArticleForm(data=data, files=files_data)
        self.assertTrue(form.is_valid())  <-- ERROR

    def test_article_crud(self):
        response = self.client.get(reverse("article:article_create"))
        self.assertEquals(response.status_code, 200)
        response = self.client.post(
            reverse("article:article_create"),
            data={
                'head': 'TEST',
                'image': self.image
            },
            follow=True,
            format='multipart'
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(Article.objects.all().count(), 1) <-- ERROR

    def test_article_view(self):
        first_article = Article.objects.create(
            pk=150,
            head='First',
            image=SimpleUploadedFile(
                name=self.image.name,
                content=self.image.read(),
                content_type='image/jpeg'
            )
        )

        second_article = Article.objects.create(
            pk=160,
            head='Second',
            image=SimpleUploadedFile(
                name=self.image.name,
                content=self.image.read(),
                content_type='image/jpeg'
            )
        )

        third_article = Article.objects.create(
            pk=170,
            head='Third',
            image=SimpleUploadedFile(
                name=self.image.name,
                content=self.image.read(),
                content_type='image/jpeg'
            )
        )
        [***]

ERROR:

FAIL: test_article_crud (article.tests.ArticleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/nurzhan/CA/article/tests.py", line 55, in test_article_crud
    self.assertEqual(Article.objects.all().count(), 1)
AssertionError: 0 != 1

======================================================================
FAIL: test_article_form_valid (article.tests.ArticleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/nurzhan/CA/article/tests.py", line 117, in test_article_form_valid
    self.assertTrue(form.is_valid())
AssertionError: False is not true

Upvotes: 7

Views: 4493

Answers (4)

The Digerati
The Digerati

Reputation: 76

I believe the best solution is to create a directory that will contain a '/media' folder, this directory can then be deleted in the tearDown function.

Based on this article, I tried the solution and it worked perfectly. You won't even notice the creation and deletion of the test directory and the files created in your tests won't be in your default media location.

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

If you want to implement this solution in DRF, your code should look like this:

from django.test import override_settings
import shutil
from rest_framework.test import APITestCase

TEST_DIR = 'test_data'

class SomeTest(APITestCase):
    ...

    # use the `override_settings` decorator on 
    # those methods where you're uploading images
    
    # do this if any logic exists to create files
    # in your setUp
    @override_settings(MEDIA_ROOT=(TEST_DIR + '/media'))
    def setUp(self):
        ...
        # your code
        ...

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

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

Upvotes: 2

Lucas Simon
Lucas Simon

Reputation: 461

I found this article and it worked to me

import shutil, tempfile
from django.test import TestCase, override_settings

MEDIA_ROOT = tempfile.mkdtemp()

@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class MeuPetTest(TestCase):
    @classmethod
    def tearDownClass(cls): 
        shutil.rmtree(MEDIA_ROOT, ignore_errors=True)
        super().tearDownClass()

Upvotes: 10

Bartlomiej Strzyga
Bartlomiej Strzyga

Reputation: 1

For me best solution was to write a function which delete images and add it into test class tearDown method.

def delete_test_image():
    images_path = os.path.join(PROJECT_PATH, 'media/images')
    files = [i for i in os.listdir(images_path) 
             if os.path.isfile(os.path.join(images_path, i))
             and i.startswith('test_image_')]

    for file in files:
        os.remove(os.path.join(images_path, file))

Upvotes: 0

zaidfazil
zaidfazil

Reputation: 9235

Use tempfile module in python, use it as settings.MEDIA_ROOT in the TestCase setUp() method,

from django.conf import settings
import tempfile

def setUp(self):
    settings.MEDIA_ROOT = tempfile.mkdtemp()

Then, the files created in the test will be automatically removed when the test is finished.

UPDATE:

Then, the files created in the test will not be automatically removed when the test is finished, so do not forget to delete the temporary directory after finishing the test.

Upvotes: 0

Related Questions