使用setUpTestData的Django测试不会保留测试之间的更改

时间:2019-10-04 10:51:10

标签: python django testing

  

classmethod TestCase.setUpTestData()

     

上述类级原子块允许在整个TestCase中一次创建类级初始数据。

     

[...]

     

请注意不要在测试方法中修改在setUpTestData()中创建的任何对象。在类级别完成的设置工作对内存中对象的修改将在测试方法之间持久存在。

引用。 django.test.TestCase.setUpTestData

考虑以下示例:

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})

因为

  

在类级别完成的设置工作中对内存对象的修改将在测试方法之间持久存在

我希望这两种测试方法之一会失败,因为post对象也将具有不同的属性,并且相等性也会失败。

但是此测试顺利通过。

如果我强制执行命令,它实际上会像预期的那样运行:

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

问题是:

在第一个示例中,测试方法是否以某种并行性运行?在某些与时间有关的巧合下,它们真的会失败吗?

有关order in which tests are executed的Django文档没有讨论测试方法。

this post中,我发现可以更改测试方法的顺序,但是一个接一个,没有并行性,除非我使用python manage.py test --parallel

1 个答案:

答案 0 :(得分:1)

这是我的测试,使用内存而不是数据库:

from django.test import TestCase

class Post(object):
    def __init__(self):
        self.stats = {}

    def refresh_from_db(self):
        pass

    def save(self):
        pass


class FoobarTest(TestCase):

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

    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})

这是我的结果:

    self.assertEquals(self.post.stats, {'foo': 1})  # this should fail
AssertionError: {'bar': 1, 'foo': 1} != {'foo': 1}
- {'bar': 1, 'foo': 1}
+ {'foo': 1}

将方法foo更改为afoo,结果如预期:

    self.assertEquals(self.post.stats, {'bar': 1})
AssertionError: {'foo': 1, 'bar': 1} != {'bar': 1}
- {'bar': 1, 'foo': 1}
+ {'bar': 1}

那么也许这是一个数据库问题?

在断言中,您正在检查内存中的对象:如果save失败,则refresh_from_db返回起始的空对象,因此将通过下一个检查。

尝试在save之后取回数据,然后检查它们。