【问题标题】:Can Django flush its database(s) between every unit test?Django 可以在每个单元测试之间刷新其数据库吗?
【发布时间】:2011-02-15 20:35:28
【问题描述】:

Django (1.2 beta) 将在每个运行的测试之间重置数据库,这意味着每个测试都在一个空数据库上运行。但是,数据库并未刷新。刷新数据库的影响之一是 auto_increment 计数器被重置。

考虑一个通过主键从数据库中提取数据的测试:

class ChangeLogTest(django.test.TestCase):
    def test_one(self):
        do_something_which_creates_two_log_entries()
        log = LogEntry.objects.get(id=1)
        assert_log_entry_correct(log)
        log = LogEntry.objects.get(id=2)
        assert_log_entry_correct(log)

这将通过,因为只创建了两个日志条目。但是,如果在ChangeLogTest 中添加另一个测试并且它恰好在之前 test_one 运行,则日志条目的主键不再是 1 和 2,它们可能是 2 和 3。现在test_one 失败。

这实际上是一个两部分的问题:

  1. 是否可以强制./manage.py test 在每个测试用例之间刷新数据库?
  2. 由于默认情况下 Django 不会在每个测试之间刷新数据库,所以也许有一个很好的理由。有人知道吗?

【问题讨论】:

    标签: database django unit-testing


    【解决方案1】:

    是否可以强制 ./manage.py test 在每个测试用例之间刷新数据库?

    看看django.core.management.commands.flush.py的命令的实现。

    你可以在你的测试调用中调用 flush 命令(可能在 TestCase.setUp 中):

    management.call_command('flush')
    

    也许有一个很好的理由。有人知道吗?

    是的,有:加快速度。从 json 刷新和重新加载许多数据需要一段时间...

    也许你应该看看TransactionTestCase

    【讨论】:

      【解决方案2】:

      答案是,不要以依赖特定键值的方式编写测试。例如,你的测试最好写成:

      def test_one(self):
          do_something_which_creates_two_log_entries()
          logs = LogEntry.objects.all()
          assert_log_entry_correct(log[0])
          assert_log_entry_correct(log[1])
      

      【讨论】:

      • 我想这会起作用,因为LogEntry.objects.all() 总是以相同的顺序(增加主键)返回记录,对吧?
      • 它是未定义的,但很可能是的。如果您想确定,只需按 id 排序结果
      • @Mike, Ivan: ..或将 ordering = ('id',) 添加到 Model.Meta
      • 编写 Daniel 建议的那种测试的一种方法是使用 jsonschema 和 Swagger 之类的东西。我想还有其他方法,但这只是对我有用的一种。
      【解决方案3】:

      你也可以使用TransactionTestCase.reset_sequences:

      在 TransactionTestCase 上设置 reset_sequences = True 将确保序列始终在测试运行之前重置:

      class TestsThatDependsOnPrimaryKeySequences(TransactionTestCase):
          reset_sequences = True
      
          def test_animal_pk(self):
              lion = Animal.objects.create(name="lion", sound="roar")
              # lion.pk is guaranteed to always be 1
              self.assertEqual(lion.pk, 1)
      

      【讨论】:

      • 只有当数据库后端有supports_sequence_reset=True时才有效,SQLite不是这样。
      猜你喜欢
      • 2015-07-25
      • 1970-01-01
      • 2014-10-15
      • 2013-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      相关资源
      最近更新 更多