测试抽象模型 - django 2.2.4 / sqlite3 2.6.0

问题描述 投票:0回答:2

我正在尝试使用 django 2.2.4/sqlite3 2.6.0/python 3.6.8 测试一些简单的抽象混合。

目前,我在使用架构编辑器从测试数据库中删除模型时遇到问题。

我有以下测试用例:

from django.test import TestCase
from django.db.models.base import ModelBase
from django.db import connection


class ModelMixinTestCase(TestCase):
    """
    Test Case for abstract mixin models.
    """
    mixin = None
    model = None

    @classmethod
    def setUpClass(cls) -> None:
        # Create a real model from the mixin
        cls.model = ModelBase(
            "__Test" + cls.mixin.__name__,
            (cls.mixin,),
            {'__module__': cls.mixin.__module__}
        )

        # Use schema_editor to create schema
        with connection.schema_editor() as editor:
            editor.create_model(cls.model)

        super().setUpClass()

    @classmethod
    def tearDownClass(cls) -> None:
        # Use schema_editor to delete schema
        with connection.schema_editor() as editor:
            editor.delete_model(cls.model)

        super().tearDownClass()

可以这样使用:

class MyMixinTestCase(ModelMixinTestCase):
    mixin = MyMixin

    def test_true(self):
        self.assertTrue(True)

这确实允许创建和测试模型。问题是,在

ModelMixinTestCase.tearDownClass
中,
connection.schema_editor()
无法禁用在
django.db.backends.sqlite3.base
中使用以下命令完成的约束检查:

    def disable_constraint_checking(self):
        with self.cursor() as cursor:
            cursor.execute('PRAGMA foreign_keys = OFF')
            # Foreign key constraints cannot be turned off while in a multi-
            # statement transaction. Fetch the current state of the pragma
            # to determine if constraints are effectively disabled.
            enabled = cursor.execute('PRAGMA foreign_keys').fetchone()[0]
        return not bool(enabled)

这会导致

__enter__
中的
DatabaseSchemaEditor
出现异常:

django.db.backends.sqlite3.schema

因此,基于所有这些,我假设我们处于原子上下文中,但我目前不确定退出该上下文并删除模型的最干净的方法是什么。

python django sqlite django-tests
2个回答
3
投票

因此,经过一番挖掘和测试后,似乎最好让 django 的

def __enter__(self): # Some SQLite schema alterations need foreign key constraints to be # disabled. Enforce it here for the duration of the schema edition. if not self.connection.disable_constraint_checking(): raise NotSupportedError( 'SQLite schema editor cannot be used while foreign key ' 'constraint checks are enabled. Make sure to disable them ' 'before entering a transaction.atomic() context because ' 'SQLite does not support disabling them in the middle of ' 'a multi-statement transaction.' ) return super().__enter__()

正常关闭事务,然后从测试数据库中删除模型。本质上我们只是首先调用

TestCase
而不是最后一个。

模型混合测试用例

因为这是一个有用的课程,我将发布完整的课程供其他人复制/粘贴。

super().tearDownClass()

使用示例1

class ModelMixinTestCase(TestCase): """ Test Case for abstract mixin models. Subclass and set cls.mixin to your desired mixin. access your model using cls.model. """ mixin = None model = None @classmethod def setUpClass(cls) -> None: # Create a real model from the mixin cls.model = ModelBase( "__Test" + cls.mixin.__name__, (cls.mixin,), {'__module__': cls.mixin.__module__} ) # Use schema_editor to create schema with connection.schema_editor() as editor: editor.create_model(cls.model) super().setUpClass() @classmethod def tearDownClass(cls) -> None: # allow the transaction to exit super().tearDownClass() # Use schema_editor to delete schema with connection.schema_editor() as editor: editor.delete_model(cls.model) # close the connection connection.close()

使用示例2

class MyMixinTestCase(ModelMixinTestCase): mixin = MyMixin def test_true(self): self.assertTrue(True)



0
投票

但是当在具有相同模型的不同测试用例上重用 mixin 时,我遇到了警告:

class SortableModelMixinTestCase(ModelMixinTestCase): mixin = SortableModelMixin def setUp(self) -> None: self.objects = [self.model.objects.create(pk=i) for i in range(10)] def test_order_linear(self) -> None: i = 1 for item in self.objects: self.assertEqual(i, item.sortable_order) i += 1

我通过检查模型是否已在应用程序中注册来解决这个问题:

RuntimeWarning: Model '<model_name>' was already registered. Reloading models is not advised as it can lead to inconsistencies, most notably with related models.

© www.soinside.com 2019 - 2024. All rights reserved.