Наследование метода 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")

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

Вернуться на верх