由於各種原因,我們使用鼻子功能測試編寫我們的測試套件。如何清理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