Django имеет два вида TestCase
: «обычный» TestCase
и TransactionTestCase
. документация содержит следующее утверждение о разнице между ними:
TransactionTestCase
и TestCase
идентичны, за исключением способа сброса базы данных до известного состояния и возможности тестового кода для проверки эффектов фиксации и отката. A TransactionTestCase
сбрасывает базу данных до запуска теста путем усечения всех таблиц и перезагрузки исходных данных. TransactionTestCase
может вызывать фиксацию и откат и наблюдать влияние этих вызовов на базу данных.
A TestCase
, с другой стороны, не усекает таблицы и не перезагружает исходные данные в начале теста. Вместо этого он включает тестовый код в транзакцию базы данных, откат которой выполняется в конце теста.
Вы используете TransactionTestCase
для выполнения этих тестов. Переключитесь на обычный TestCase
, и вы увидите, что проблема исчезает при условии вы поддерживаете существующий тестовый код.
Почему это происходит? TestCase
выполняет методы тестирования внутри блока транзакции. Это означает, что каждый тестовый метод в вашем тестовом классе будет выполняться внутри отдельной транзакции, а не в одной транзакции. Когда утверждение (или, точнее, lambda
внутри) выдает ошибку, оно умирает с транзакцией. Следующий тестовый метод выполняется в новой транзакции, и поэтому вы не видите ошибку, которую получаете.
Однако, если бы вы добавили другое идентичное утверждение в таком же методе проверки, вы бы снова увидели ошибку:
class TransProblemTest(django.test.TestCase):
def test_uniqueness1(self):
User.objects.create_user(username='user1', email='user1@example.com', password='secret')
self.assertRaises(IntegrityError, lambda :
User.objects.create_user(username='user1', email='user1@example.com', password='secret'))
# Repeat the test condition.
self.assertRaises(IntegrityError, lambda :
User.objects.create_user(username='user1', email='user1@example.com', password='secret'))
Это вызвано тем, что первое утверждение создаст ошибку, которая приведет к прерыванию транзакции. Поэтому второе не может быть выполнено. Поскольку оба утверждения происходят внутри одного и того же метода тестирования, новая транзакция не была инициирована в отличие от предыдущего случая.
Надеюсь, это поможет.