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

ecr0jaav  于 2022-11-26  发布在  Go
关注(0)|答案(4)|浏览(181)

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在每个测试用例之间刷新数据库?
1.由于Django在默认情况下不会在每次测试之间刷新数据库,这可能是有原因的,有人知道吗?

qqrboqgw

qqrboqgw1#

是否可以强制./manage.py测试在每个测试用例之间刷新数据库?
查看一下django.core.management.commands.flush.py命令的实现。
你可以从你的测试调用内部调用flush命令(也许在TestCase.setUp中):

management.call_command('flush')

也许这是有原因的,有人知道吗
有:加速。从json刷新和重新加载许多数据需要一段时间...
也许你应该看看TransactionTestCase

rqdpfwrv

rqdpfwrv2#

答案是,不要用依赖于特定键值的方式来编写测试。例如,你的测试可以更好地编写为:

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])
czq61nw1

czq61nw13#

您也可以使用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)
b4qexyjb

b4qexyjb4#

如果您使用任何类型的“刷新”,请记住,如果您已经自动创建用户或任何其他类型的数据插入,它也将被删除。
解决这个问题而不刷新的一个简单方法是在测试期间获取第一个对象的ID并从那里递增。

Test1:
assertEqual(foo.id, 1)
assertEqual(bar.id, 2)

Test2:
start_id = Foo.objects.first().id
assertEqual(foo.id, start_id)
assertEqual(bar.id, (start_id + 1))

相关问题