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

标签 python django testing

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.

引用。 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})

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

我预计这两种测试方法中的一种会失败,因为 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

最佳答案

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

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 返回起始空对象,因此下一次检查通过。

尝试在保存后取回数据,然后检查它们。

关于python - 使用 setUpTestData 的 Django 测试不会保留测试之间的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58234957/

相关文章:

javascript - javascript中的函数调用

django - 使用内联时如何验证 django-admin 中两个模型的数据?

javascript - 访问包装在高阶组件中的组件中的实例方法 - React.js

python - 使用元素树解析 wsdl(从定义中检索 namespace )

python - 反转递归产生的整数的顺序

javascript - 如何在html和javascript中声明全局变量

javascript - 通过使用 chai-as-promised 的函数调用验证已解决 promise 的内容

testing - 有关 docker、测试环境和开发工作流程的查询

python - 使用 Python 使用 SSH 从服务器读取文件

python - 不包括前导零的随机数的排列