Как я могу очистить изменения базы данных, сделанные в тестовых функциях django-nose?

Мы пишем наш набор тестов, используя тесты функции носа по разным причинам.

При запуске набора тестов для нашего приложения Django мы хотели бы избежать утечки каких-либо данных из этих тестов (как в случае с django.test.TestCase), потому что это приводит к связанности и затрудняет диагностику сбоев.

Наиболее очевидным средством решения этой проблемы является декоратор, который мы можем просто обернуть вокруг тестов, которые мы хотим очистить после, но я не женат на этом, если другое решение может дать нам то, что мы хотим.

Мы работаем на PostgreSQL, поэтому решения, специфичные для Postgres, подойдут.


person Daniel Watkins    schedule 21.02.2013    source источник
comment
django автоматически удаляет базу данных при каждом запуске теста, создавая изолированную тестовую среду.   -  person dm03514    schedule 21.02.2013
comment
@ dm03514 dm03514 Немного покопавшись, я понял, что это происходит с тестовыми функциями django-nose, а не с более общим случаем, с которым я изначально сформулировал вопрос.   -  person Daniel Watkins    schedule 21.02.2013


Ответы (1)


Я потратил немного времени, глядя на это сегодня, и придумал следующий декоратор:

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())

Ранее второй тест не мог создать пользователя с повторяющимся именем пользователя.

person Daniel Watkins    schedule 22.02.2013
comment
Ну, строго говоря, эти тесты проваливаются, потому что другие места в нашей кодовой базе не наводят порядок. Но вы поняли. - person Daniel Watkins; 22.02.2013