当前位置:  开发笔记 > 编程语言 > 正文

Django:如何动态创建模型以进行测试

如何解决《Django:如何动态创建模型以进行测试》经验,为你挑选了7个好方法。

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

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

然后挂钩他们的post_save信号,根据attributeN定义更新一些其他固定模型.

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

允许我使用测试夹具的解决方案会很棒.



1> Carl Meyer..:

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

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

(注意:下面描述的替代动态方法仅适用于Django 1.1+,如果您的测试用例子类TransactionTestCase- 这会显着减慢您的测试速度 - 并且在Django 1.7+中根本不再有用.它只留给历史兴趣;不要用它.)

在测试开始时(即在setUp方法中,或在一组doctests的开头),您可以动态添加"myapp.tests"到INSTALLED_APPS设置,然后执行以下操作:

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

然后在测试结束时,您应该通过恢复旧版本的INSTALLED_APPS并再次清除应用缓存来进行清理.

这个类封装了模式,因此它不会使测试代码混乱不堪.



2> Conley Owens..:

@ paluh的答案需要在非测试文件中添加不需要的代码,根据我的经验,@ carl的解决方案不适用于使用灯具所需的django.test.TestCase.如果你想使用django.test.TestCase,你需要确保在加载灯具之前调用syncdb.这需要覆盖_pre_setup方法(将代码放入setUp方法是不够的).我使用自己的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


为了使这与[South](http://south.aeracode.org/)一起使用,我必须将`migrate = False`传递给call_command.
如果您已将settings.INSTALLED_APPS定义为元组(如django文档中所提议的那样),则首先必须将其转换为列表.否则它工作正常.

3> paluh..:

此解决方案仅适用于django(之前1.7)的早期版本.您可以轻松查看您的版本:

import django
django.VERSION < (1, 7)

原始回复:

这很奇怪,但形式我的作品非常简单:

    将tests.py添加到您要测试的应用中,

    在这个文件中只定义测试模型,

    下面放你的测试代码(doctest或TestCase定义),

下面我给出了一些定义了仅用于测试的Article模型的代码(它存在于someapp/tests.py中,我可以用以下方法测试它:./ manage.py test someapp):

class Article(models.Model):
    title = models.CharField(max_length=128)
    description = models.TextField()
    document = DocumentTextField(template=lambda i: i.description)

    def __unicode__(self):
        return self.title

__test__ = {"doctest": """
#smuggling model for tests
>>> from .tests import Article

#testing data
>>> by_two = Article.objects.create(title="divisible by two", description="two four six eight")
>>> by_three = Article.objects.create(title="divisible by three", description="three six nine")
>>> by_four = Article.objects.create(title="divisible by four", description="four four eight")

>>> Article.objects.all().search(document='four')
[, ]
>>> Article.objects.all().search(document='three')
[]
"""}

单元测试也使用这种模型定义.



4> Kirill Ermol..:

我分享了我在项目中使用的解决方案.也许它有助于某人.

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)将装饰器添加@MyFakeModel.fake_meTestCase或测试功能.

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

此装饰器在每次测试之前在数据库中创建表,并在测试后删除表.

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



5> Jashugan..:

我选择了一种稍微不同的,虽然更加耦合的方法来动态创建仅用于测试的模型.

我将所有测试保存tests在我的files应用程序中的子目录中.子目录中的models.py文件tests包含我的仅测试模型.耦合部分在这里,我需要将以下内容添加到我的settings.py文件中:

# check if we are testing right now
TESTING = 'test' in sys.argv

if TESTING:
    # add test packages that have models
    INSTALLED_APPS += ['files.tests',]

我还在我的测试模型中设置了db_table,因为否则Django会创建带有名称的表tests_,这可能会导致与另一个应用程序中的其他测试模型发生冲突.这是我的测试模型:

class Recipe(models.Model):

    '''Test-only model to test out thumbnail registration.'''

    dish_image = models.ImageField(upload_to='recipes/')

    class Meta:
        db_table = 'files_tests_recipe'



6> 小智..:

引用相关答案:

如果您只想为测试定义模型,那么您应该查看 Django机票#7835特别注释#24部分如下:

显然,您可以直接在tests.py中定义模型.Syncdb从不导入tests.py,因此这些模型不会同步到普通数据库,但它们将同步到测试数据库,并可用于测试.


Django 1.7+没有"syncdb".自从我调查以来已经至少一年了,但是如果我没记错的话,AppConfig.ready()仅在构建数据库并运行所有迁移后调用,并且在AppConfig.ready之后甚至不会加载测试模块( ).您可能能够通过自定义测试运行器,settings.py或AppConfig来破解某些东西,但是我无法获得可以使用该模型中的put-the-models的明显变体.如果某人有一个Django 1.7+这样的例子,我会很高兴看到它.

7> Xiao Hanyu..:

我已经找到了django 1.7+测试模型的方法.

基本思路是,让你的tests应用程序,并添加testsINSTALLED_APPS.

这是一个例子:

$ ls common
__init__.py   admin.py      apps.py       fixtures      models.py     pagination.py tests         validators.py views.py

$ ls common/tests
__init__.py        apps.py            models.py          serializers.py     test_filter.py     test_pagination.py test_validators.py views.py

我有不同settings的目的(参考:拆分设置文件),即:

settings/default.py:基本设置文件

settings/production.py:用于生产

settings/development.py:用于发展

settings/testing.py: 用于检测.

settings/testing.py,你可以修改INSTALLED_APPS:

settings/testing.py:

from default import *

DEBUG = True

INSTALLED_APPS += ['common', 'common.tests']

并确保为测试应用设置了适当的标签,即

common/tests/apps.py

from django.apps import AppConfig


class CommonTestsConfig(AppConfig):
    name = 'common.tests'
    label = 'common_tests'

common/tests/__init__.py,设置正确AppConfig(参考:Django应用程序).

default_app_config = 'common.tests.apps.CommonTestsConfig'

然后,生成db migration by

python manage.py makemigrations --settings=.settings.testing tests

最后,您可以使用param运行测试--settings=.settings.testing.

如果你使用py.test,你甚至可以删除pytest.inidjango的文件manage.py.

py.test

[pytest]
DJANGO_SETTINGS_MODULE=kungfu.settings.testing

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有