代码之家  ›  专栏  ›  技术社区  ›  Mike Mazur

django可以在每个单元测试之间刷新它的数据库吗?

  •  7
  • Mike Mazur  · 技术社区  · 15 年前

    django(1.2beta)将在运行的每个测试之间重置数据库,这意味着每个测试都在空数据库上运行。但是,数据库不是 冲洗的 . 刷新数据库的一个效果是 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。现在 试验一 失败。

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

    1. 有可能强迫 ./manage.py test 在每个测试用例之间刷新数据库?
    2. 由于django在默认情况下不会在每个测试之间刷新db,也许有一个很好的原因。有人知道吗?
    3 回复  |  直到 7 年前
        1
  •  7
  •   maersu    15 年前

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

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

    您可以从测试调用内部调用flush命令(可能在testcase.setup中):

    management.call_command('flush')
    

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

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

    也许你该看看 TransactionTestCase

        2
  •  8
  •   Daniel Roseman    15 年前

    答案是,不要以这种方式编写测试,因为它们依赖于特定的键值。例如,你的测试最好写在:

    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])
    
        3
  •  0
  •   andyandy    7 年前

    你也可以使用 TransactionTestCase.reset_sequences :

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

    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)