Django тестирует commit_on_success

У меня есть функция, которую я завернул в @transaction.commit_on_success и запускаю на ней модульные тесты Django.

Функция слишком длинная для вставки, но есть такой псевдокод:

@transaction.commit_on_success
def func():
  order = Order.create()
  order.save()
  OrderItem.create(order=order)
  test = 10/0 # make sure we run into an error

Затем в моем модульном тесте я проверяю, len(Order.objects.all()) == 0

Моя функция возвращает действительный объект Order, поэтому транзакция фиксируется.

Что я здесь делаю неправильно?

РЕДАКТИРОВАТЬ: я на Django 1.5


person grokpot    schedule 29.08.2015    source источник


Ответы (3)


Догадаться.

Мне нужно использовать TransactionTestCase (без документации на 1,5).

TransactionTestCase может вызывать фиксацию и откат и наблюдать за влиянием этих вызовов на базу данных.

Я сталкивался с этим раньше, но пытался использовать его в тандеме с TestCase. Они взаимоисключающие, и ваш модульный тест может использовать только один или другой. Поскольку мы используем пользовательский тестовый класс, мне пришлось немного маневрировать, но теперь все откатывается правильно.

Также похоже, что Django 1.8 TestCase теперь поддерживает тестирование транзакций:

В более старых версиях Django эффекты фиксации и отката транзакции нельзя было протестировать в TestCase. С завершением цикла устаревания управления транзакциями старого стиля в Django 1.8 команды управления транзакциями (например, transaction.commit()) больше не отключаются в TestCase.

Спасибо Джону и Сиракой за ваши ответы. В любом случае, наверное, лучше обновиться с 1.5;)

person grokpot    schedule 30.08.2015
comment
Я бы, конечно, рекомендовал обновить. :) - person John Percival Hackworth; 30.08.2015

Если вы используете MySQL, ваша таблица может не поддерживать транзакции. Подробнее см. документацию Django по транзакциям. .

person John Percival Hackworth    schedule 29.08.2015
comment
Я использую Postgres и уже просмотрел документы. Спасибо хоть! - person grokpot; 29.08.2015

Вместо этого вы должны использовать @transaction.atomic, commit_on_success устарел, начиная с django 1.6, поскольку он ненадежен.

Для получения дополнительной информации ознакомьтесь с этим ответом: Является ли transaction.atomic таким же, как transaction.commit_on_success?

Изменить (поскольку вы используете 1.5):

Возможный обходной путь для этого — использовать @transaction.commit_manually, как показано здесь: https://docs.djangoproject.com/en/1.5/topics/db/transactions/#django.db.transaction.commit_manually

person siracoj    schedule 29.08.2015
comment
Наш стек использует 1.5. Хотя я мог бы подумать об обновлении Django, я бы предпочел выяснить, что происходит в нашей текущей версии. - person grokpot; 30.08.2015
comment
Спасибо за ваше редактирование. Я думаю, что я собираюсь продолжить эту стратегию. Итак, я предполагаю, что это просто ошибка с commit_on_success? - person grokpot; 30.08.2015
comment
@grokpot Да, это ненадежно, как сказано в ответе, который я связал. Возможно, он совершил эту ошибку или не смог выполнить откат - person siracoj; 30.08.2015