Класс TransactionTestCase

Класс TransactionTestCase является подклассом TestCase и предназначен для тестирования сценариев, связанных с транзакциями базы данных. В отличие от обычного TestCase, который оборачивает каждый тест в транзакцию и откатывает её после выполнения, TransactionTestCase не использует транзакционную обёртку. Это позволяет проверять поведение кода при работе с реальными транзакциями, включая их фиксацию и откат. Основные параметры класса включают available_apps для ограничения набора приложений при сбросе базы данных, databases для указания используемых баз данных и serialized_rollback для управления откатом данных между тестами.

Особенности работы

Основное отличие TransactionTestCase от TestCase заключается в том, что каждый тестовый метод выполняется в отдельной транзакции, но изменения в базе данных фиксируются. После завершения теста база данных сбрасывается до исходного состояния с помощью усечения таблиц или перезагрузки данных. Это делает TransactionTestCase более медленным, но необходимым для тестирования транзакционной логики.

Синтаксис

pythonfrom django.test import TransactionTestCase

class MyTransactionTest(TransactionTestCase):
  def test_transaction_logic(self):
    # Тестовый код
    pass

Пример . С откатом транзакции

Давайте проверим, что транзакция откатывается при возникновении исключения:

pythonfrom django.test import TransactionTestCase
from django.db import transaction
from myapp.models import Article

class TransactionTest(TransactionTestCase):
  def test_transaction_rollback(self):
    with self.assertRaises(Exception):
      with transaction.atomic():
        Article.objects.create(title="Test Article")
        raise Exception("Rollback test")

    # Проверяем, что статья не была создана
    count = Article.objects.count()
    self.assertEqual(count, 0)

Результат выполнения кода:

python"Test passed"

Пример . С фиксацией транзакции

Рассмотрим сценарий, где транзакция успешно фиксируется:

pythonfrom django.test import TransactionTestCase
from django.db import transaction
from myapp.models import Article

class TransactionCommitTest(TransactionTestCase):
  def test_transaction_commit(self):
    with transaction.atomic():
      article = Article.objects.create(title="Saved Article")

    # Проверяем, что статья была создана
    count = Article.objects.count()
    self.assertEqual(count, 1)
    self.assertEqual(article.title, "Saved Article")

Результат выполнения кода:

python"Test passed"

Использование setUp

Метод setUp в TransactionTestCase выполняется перед каждым тестом и не является транзакционным. Изменения, сделанные в setUp, будут зафиксированы, как и в основном тесте:

pythonfrom django.test import TransactionTestCase
from myapp.models import Article

class SetUpTransactionTest(TransactionTestCase):
  def setUp(self):
    Article.objects.create(title="SetUp Article")

  def test_setup_data_exists(self):
    count = Article.objects.count()
    self.assertEqual(count, 1)

  def test_another_test_also_sees_data(self):
    count = Article.objects.count()
    self.assertEqual(count, 1)

Результат выполнения кода:

python"Tests passed"

Смотрите также

  • класс TestCase,
    который используется для стандартных тестов с автоматическим откатом транзакций
  • класс SimpleTestCase,
    который предназначен для тестов без взаимодействия с базой данных
  • класс LiveServerTestCase,
    который запускает живой сервер для тестирования с внешними инструментами
  • метод setUpTestData,
    который создаёт данные один раз для всех тестов в классе