我有一个带“标题” CharField(unique=True)的Django模型。我有一个单元测试,断言创建具有相同标题的第二个实例会引发IntegrityError。 (我正在使用pytest和pytest-django。)

我有类似的东西:

class Foo(models.Model):
    title = models.CharField(unique=True)

def test_title_is_unique(db):
    Foo.objects.create(title='foo')
    with pytest.raises(IntegrityError):
        Foo.objects.create(title='foo')


除上面的代码不包含清除代码外,此方法工作正常。 pytest-django不会为您清理数据库,因此在创建或保存模型实例时需要注册清理处理程序。像这样:

def test_title_is_unique(request, db):
    foo = Foo.objects.create(title='foo')
    request.addfinalizer(foo.delete)
    with pytest.raises(IntegrityError):
        Foo.objects.create(title='foo')


好的,很好。但是,如果第二个.create()调用错误地成功了怎么办?我仍然想清理该实例,但前提是(错误地)创建了该实例。

这是我确定的:

def test_title_is_unique(request, db):
    foo = Foo.objects.create(title='foo')
    request.addfinalizer(foo.delete)
    try:
        with pytest.raises(IntegrityError):
            new_foo = Foo.objects.create(title='foo')
    finally:
        if 'new_foo' in locals():
            request.addfinalizer(new_foo.delete)


这并没有特别优雅或Pythonic的感觉,更不用说有一堆真正不应该运行的代码了。

我如何保证第二个模型实例在创建后就被清理了,但是要跳过的箍更少和/或使用的代码行更少?

最佳答案

您无需担心清理。 pytest-django的db夹具禁用测试的事务,在一个事务中执行整个测试,并在最后回滚该事务。这样可以确保数据库保持干净。

如果测试需要事务,则有transactional_db固定装置,它将启用事务(较慢)并在测试后刷新数据库的全部内容(非常慢),再次为您清理。

因此,如果清理没有发生,那么您可能应该在pytest-django上提交错误。但是,如果真是这样,除非我错过了重要的事情,否则我会感到惊讶。

关于python - 在引发断言为IntegrityError的单元测试后进行清理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22507746/

10-12 12:39