继承为每个 child 调用的 Django SetUpTestData 方法

Inherinting Django SetUpTestData method called for each child

继承母亲 class 使其 class 方法 setUpTestData 调用每个 child class。这是我例外但不是我想要的。

这是一个极简主义的例子

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'...

我希望能够制作许多 child class,其中每个 child class 都会对公共 'inherited' 数据库进行微小的修改。但是我不想 运行 多次使用 parent class 方法,因为它非常慢。

如何确保 parent 数据库仅生成一次,并且每个 child class 都在 parent 数据库的副本上工作,而不是重新生成整个数据库。

正如您自己所说,@brian-destura 也指出,在测试 类 之间共享数据的最佳选择是实施您自己的测试运行器。

跑步者应该继承自django.test.runner.DiscoverRunner。 在该跑步者中,您可以根据需要覆盖 setup_test_environment() (docs) or setup_databases() (docs)。

Finngu 的建议绝对有效。然而 - 拆分测试的一个重要原因是让它们 运行 在单独的数据库事务中。通过共享数据库设置,您在某种程度上打败了重点。

要进行共享数据库设置的独立测试,您可以只使用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")

这些子测试 运行 独立 - 这意味着如果一个子测试失败,测试将继续 运行ning。这与自定义测试 运行ner 是一个将归结为细节的决定,但在大多数情况下子测试是有效且足够的。阅读更多关于它们的信息,即:here.