Django:如何动态创建用于测试的模型

2024-09-30 22:27:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Django应用程序需要一个settings属性,其形式如下:

RELATED_MODELS = ('appname1.modelname1.attribute1',
                  'appname1.modelname2.attribute2', 
                  'appname2.modelname3.attribute3', ...)

然后,根据定义的attributeN,挂接它们的postúu save信号以更新其他一些固定模型。

我想测试这个行为,即使这个应用程序是项目中唯一的一个,测试也应该有效(除了它自己的依赖项,不需要安装其他包装应用程序)。如何仅为测试数据库创建和附加/注册/激活模拟模型?(或者有可能吗?)

解决方案,让我使用测试夹具将是伟大的。


Tags: django应用程序属性settingsmodels形式relatedappname1
3条回答

您可以将测试放在应用程序的tests/子目录(而不是tests.py文件)中,并在仅测试的模型中包含tests/models.py

然后提供一个测试运行脚本(example),其中包含INSTALLED_APPS中的tests/“应用程序”。(当从实际项目运行应用程序测试时,这不起作用,因为实际项目中没有测试应用程序,INSTALLED_APPS,但我很少发现从项目运行可重用的应用程序测试有用,而Django 1.6+默认情况下不起作用。)

注意:下面描述的可选动态方法仅在Django 1.1+中有效,前提是您的测试用例子类TransactionTestCase显著减慢了您的测试速度,并且不再在Django 1.7+中有效。它留在这里只是为了历史利益,不要用它。)

在测试开始时(即在安装方法中,或在一组doctest开始时),可以动态地将"myapp.tests"添加到“已安装的应用程序”设置中,然后执行以下操作:

from django.core.management import call_command
from django.db.models import loading
loading.cache.loaded = False
call_command('syncdb', verbosity=0)

然后在测试结束时,应通过还原已安装的旧版本的应用程序并再次清除应用程序缓存来进行清理。

This class封装了模式,这样就不会把测试代码弄得那么混乱。

@paluh的答案要求在非测试文件中添加不需要的代码,根据我的经验,@carl的解决方案不适用于使用fixture所需的django.test.TestCase。如果要使用django.test.TestCase,则需要确保在加载设备之前调用syncdb。这需要重写预安装方法(仅将代码放入安装方法是不够的)。我使用自己的TestCase版本,让我添加带有测试模型的应用程序。定义如下:

from django.conf import settings
from django.core.management import call_command
from django.db.models import loading
from django import test

class TestCase(test.TestCase):
    apps = ()

    def _pre_setup(self):
        # Add the models to the db.
        self._original_installed_apps = list(settings.INSTALLED_APPS)
        for app in self.apps:
            settings.INSTALLED_APPS.append(app)
        loading.cache.loaded = False
        call_command('syncdb', interactive=False, verbosity=0)
        # Call the original method that does the fixtures etc.
        super(TestCase, self)._pre_setup()

    def _post_teardown(self):
        # Call the original method.
        super(TestCase, self)._post_teardown()
        # Restore the settings.
        settings.INSTALLED_APPS = self._original_installed_apps
        loading.cache.loaded = False

我分享了我在项目中使用的solution。也许它能帮助别人。

pip install django-fake-model

创建假模型的两个简单步骤:

1)在任何文件中定义模型(我通常在测试用例附近的测试文件中定义模型)

from django_fake_model import models as f


class MyFakeModel(f.FakeModel):

    name = models.CharField(max_length=100)

2)将decorator@MyFakeModel.fake_me添加到TestCase或测试函数。

class MyTest(TestCase):

    @MyFakeModel.fake_me
    def test_create_model(self):
        MyFakeModel.objects.create(name='123')
        model = MyFakeModel.objects.get(name='123')
        self.assertEqual(model.name, '123')

这个decorator在每次测试之前在数据库中创建表,并在测试之后删除表。

您还可以手动创建/删除表:MyFakeModel.create_table()/MyFakeModel.delete_table()

相关问题 更多 >