Home > Net >  Django setUpTestData does not deepcopy related files
Django setUpTestData does not deepcopy related files

Time:03-23

I want to use django setUpTestData to prepare some heavy data shared between multiples unit tests. Instances of my Model are created with some file fields.

However, from one test to another, file contents are not renewed, it has side effects between my tests

here is a minimalist example :

models.py

from django.db import models


class MyModel(models.Model):
    my_file = models.FileField(upload_to="tests/")

test.py

from django.core.files.base import ContentFile
from django.test import TestCase

from core.models import MyModel


class Test(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.instance = MyModel()
        cls.instance.my_file.save("file.txt", ContentFile("Hello from setUpTestData"))

    def test_a(self):
        with open(self.instance.my_file.path, "r") as fp:
            self.assertEqual(fp.read(), "Hello from setUpTestData")
        self.instance.my_file.save("file.txt", ContentFile("Modified data"))

    def test_b(self):
        with open(self.instance.my_file.path, "r") as fp:
            self.assertEqual(fp.read(), "Hello from setUpTestData")
        self.instance.my_file.save("file.txt", ContentFile("Modified data"))

Running any of the two test alone works, however running one after the other one fails:

AssertionError: 'Modified datatUpTestData' != 'Hello from setUpTestData'
- Modified datatUpTestData
  Hello from setUpTestData

How to ensure that file are correctly reset? Am I concerned by theses lines from the documentation ?

Objects assigned to class attributes in setUpTestData() must support creating deep copies with copy.deepcopy()

I feel like fileField should be handled by default by Django but it doesn't work, what should I do? Should I try to override __deepcopy__ for my models? Modifying my code for testing purpose is a bad pattern.

CodePudding user response:

I've found a solution by using setUp and tearDown

def setUp(self) : # copy original files
    shutil.copytree(settings.MEDIA_ROOT, "/tmp/tests", dirs_exist_ok=True)

def tearDown(self) : # restore original files
    shutil.copytree("/tmp/tests", settings.MEDIA_ROOT, dirs_exist_ok=True)
  • Related