由于各种原因,我们使用鼻子功能测试编写我们的测试套件。如何清理django-nose测试功能中的数据库更改?
当为我们的Django应用程序运行测试套件时,我们希望避免泄漏任何数据(如django.test.TestCase
),因为这会导致耦合并难以诊断故障。
解决这个问题的最明显的方法是装饰器,我们可以将测试包裹起来,然后我们就可以将其清理干净,但如果不同的解决方案能够获得我们想要的结果,我就不会结婚。
我们在PostgreSQL上运行,所以Postgres特定的解决方案将会很好。
由于各种原因,我们使用鼻子功能测试编写我们的测试套件。如何清理django-nose测试功能中的数据库更改?
当为我们的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())
以前第二次测试运行无法创建具有重复的用户名的用户。
嗯,严格来说,那些测试失败了,因为我们的代码库中的其他地方没有清理他们的混乱。但你明白了。 – 2013-02-22 10:25:56
django在每次测试运行时自动关闭数据库,这会创建一个独立的测试环境 – dm03514 2013-02-21 17:24:08
@ dm03514经过一番探索之后,我意识到这是发生在django-nose测试功能上的,而不是更一般的情况我最初是用这个问题起草的。 – 2013-02-21 17:27:31