vendredi 4 octobre 2019

Django test with setUpTestData doesn't keep changes between tests

classmethod TestCase.setUpTestData()

The class-level atomic block described above allows the creation of initial data at the class level, once for the whole TestCase.

[...]

Be careful not to modify any objects created in setUpTestData() in your test methods. Modifications to in-memory objects from setup work done at the class level will persist between test methods.

Cit. django.test.TestCase.setUpTestData

Consider this example:

class FoobarTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.post = Post()
        cls.post.stats = {}
        cls.post.save()

    def setUp(self):
        self.post.refresh_from_db()

    def test_foo(self):
        self.post.stats['foo'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'foo': 1}) # this should fail

    def test_bar(self): # this run first cause alphabetical order
        self.post.stats['bar'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'bar': 1})

Since

Modifications to in-memory objects from setup work done at the class level will persist between test methods

I expect one of the two test methods to fail cause the post object will have also a different property and the equality should fail.

But this test pass without problem.

If i force the execution order it actually behave like expected:

class FoobarTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.post = Post()
        cls.post.stats = {}
        cls.post.save()

    def setUp(self):
        self.post.refresh_from_db()

    def _foo(self):
        self.post.stats['foo'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'foo': 1})

    def _bar(self):
        self.post.stats['bar'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'bar': 1})

    def test_foo_bar(self):
        self._foo()
        self._bar() # this fail

The question is:

in the first example, are the test methods running in some kind of parallelism? Can they actually fails under some time-related coincidences?

The Django docs about order in which tests are executed doens't talk about test methods.

In this post i found that the order of test methods can be changed, but is one after another, without parallelism, unless i use python manage.py test --parallel.

Aucun commentaire:

Enregistrer un commentaire