出于各种原因,我们使用鼻子功能测试来编写我们的测试套件。
在为我们的 Django 应用程序运行测试套件时,我们希望避免从这些测试中泄漏任何数据(如django.test.TestCase
),因为这会导致耦合并且难以诊断故障。
解决这个问题最明显的方法是一个装饰器,我们可以将它包裹起来,然后我们想要清理的测试,但如果一个不同的解决方案可以得到我们想要的东西,我不会结婚。
我们在 PostgreSQL 上运行,因此特定于 Postgres 的解决方案会很好。
出于各种原因,我们使用鼻子功能测试来编写我们的测试套件。
在为我们的 Django 应用程序运行测试套件时,我们希望避免从这些测试中泄漏任何数据(如django.test.TestCase
),因为这会导致耦合并且难以诊断故障。
解决这个问题最明显的方法是一个装饰器,我们可以将它包裹起来,然后我们想要清理的测试,但如果一个不同的解决方案可以得到我们想要的东西,我不会结婚。
我们在 PostgreSQL 上运行,因此特定于 Postgres 的解决方案会很好。
我今天花了一些时间看这个,并提出了以下装饰器:
from functools import wraps
from django.db import transaction
from mock import patch
def rollback_db_changes(func):
"""Decorate a function so that it will be rolled back once completed."""
@wraps(func)
@transaction.commit_manually
def new_f(*args, **kwargs):
def fake_commit(using=None):
# Don't properly commit the transaction, so we can roll it back
transaction.set_clean(using)
patcher = patch('django.db.transaction.commit', fake_commit)
patcher.start()
try:
return func(*args, **kwargs)
finally:
patcher.stop()
transaction.rollback()
return new_f
我们执行修补,以便 Django 测试客户端在我们无法回滚的情况下不会关闭事务。这允许以下测试通过:
from django.contrib.auth.models import User
@rollback_db_changes
def test_allowed_access():
user = User.objects.create(username='test_user')
eq_(1, User.objects.count())
@rollback_db_changes
def test_allowed_access_2():
user = User.objects.create(username='test_user')
eq_(1, User.objects.count())
以前要运行的第二个测试无法创建具有重复用户名的用户。