Наследование метода Django SetUpTestData, вызываемого для каждого ребенка
При наследовании материнского класса его классметод setUpTestData вызывается для каждого дочернего класса. Это то, что я исключил, но не то, что я хочу.
Вот минималистский пример
from django.test import TestCase
class ParentClass(TestCase):
@classmethod
def setUpTestData(cls):
cls.parent_attr = "parent value"
print("ParentClass.setUpTestData called") # this is called twice
class TestChild1(ParentClass):
@classmethod
def setUpTestData(cls):
super(TestChild1, cls).setUpTestData()
cls.child_attr = "child value 1"
def test_child(self):
self.assertEqual(self.parent_attr, "parent value")
self.assertEqual(self.child_attr, "child value 1")
class TestChild2(ParentClass):
@classmethod
def setUpTestData(cls):
super(TestChild2, cls).setUpTestData()
cls.child_attr = "child value 2"
def test_child(self):
self.assertEqual(self.parent_attr, "parent value")
self.assertEqual(self.child_attr, "child value 2")
$ python manage.py test accounts.tests.test_test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
ParentClass.setUpTestData called
.ParentClass.setUpTestData called
.
----------------------------------------------------------------------
Ran 2 tests in 0.006s
OK
Destroying test database for alias 'default'...
Я хочу иметь возможность сделать много дочерних классов, где каждый дочерний класс будет применять крошечные модификации к общей "унаследованной" базе данных. Однако я не хочу запускать много раз метод родительского класса, так как это очень медленно.
Как сделать так, чтобы родительская база данных создавалась только один раз и чтобы каждый дочерний класс работал с копией родительской базы данных, а не регенерировал всю базу данных.
Как вы сами заявили, а также отметил @brian-destura, лучшим вариантом для обмена данными между тестовыми классами будет реализация собственной программы запуска тестов.
Бегунок должен наследоваться от django.test.runner.DiscoverRunner.
В этом бегуне вы можете переопределить setup_test_environment() (docs) или setup_databases() (docs) в зависимости от ваших потребностей.
Предложение Финнгу абсолютно точно работает. Однако - большая причина для разделения тестов заключается в том, чтобы они выполнялись в отдельных транзакциях БД. Разделяя настройку базы данных, вы в некоторой степени лишаете себя смысла.
Для создания независимых тестов, имеющих общую настройку БД, вы можете просто использовать subTest.
from django.test import TestCase
class TestSubTests(ParentClass):
@classmethod
def setUpTestData(cls):
super(TestChild1, cls).setUpTestData()
cls.parent_attr = "parent value"
def test_subtests(self):
with self.subTest("The first value"):
child_attr = "child value 1"
self.assertEqual(self.parent_attr, "parent value")
self.assertEqual(self.child_attr, "child value 1")
with self.subTest("The second value"):
child_attr = "child value 2"
self.assertEqual(self.parent_attr, "parent value")
self.assertEqual(self.child_attr, "child value 2")
Эти подтесты выполняются независимо - это означает, что тест продолжает выполняться, если один подтест не работает. Решение о сравнении с пользовательским тестовым бегунком сводится к деталям, но субтесты эффективны и достаточны в большинстве случаев. Подробнее о них читайте здесь