测试中的模型 - Django 1.7 问题

Posted

技术标签:

【中文标题】测试中的模型 - Django 1.7 问题【英文标题】:Models inside tests - Django 1.7 issue 【发布时间】:2014-10-29 10:16:27 【问题描述】:

我正在尝试移植我的项目以使用 Django 1.7。一切都很好,除了 1 件事。测试文件夹中的模型。

Django 1.7 新迁移在内部运行 migrate 命令。在运行 syncdb 之前。这意味着如果模型不包含在迁移中 - 它不会填充到数据库(也不会填充到测试数据库)。这正是我现在所经历的。

我做的是:

在我的/app/tests/models.py 我有虚拟模型:class TestBaseImage(BaseImage): pass 它所做的只是从 abstract BaseImage 模型继承。

然后在测试中我创建该虚拟模型的实例来测试它。

问题是它不再起作用了。它不包含在迁移中(这很明显,因为我不想将我的测试模型保留在生产数据库中)。运行我的测试会导致数据库错误说table does not exist。这是有道理的,因为它不包含在迁移中。

有没有办法让它与新的迁移系统一起工作?我找不到“修复”它的方法。

我使用的代码:

app/tests/models.py

from ..models import BaseImage


class TestBaseImage(BaseImage):
    """Dummy model just to test BaseImage abstract class"""
    pass

app/models.py

class BaseImage(models.Model):
    # ... fields ...
    class Meta:
        abstract = True

工厂:

class BaseImageFactory(factory.django.DjangoModelFactory):
    """Factory class for Vessel model"""
    FACTORY_FOR = BaseImage
    ABSTRACT_FACTORY = True


class PortImageFactory(BaseImageFactory):
    FACTORY_FOR = PortImage

示例测试:

def get_model_field(model, field_name):
    """Returns field instance"""
    return model._meta.get_field_by_name(field_name)[0]


def test_owner_field(self):
    """Tests owner field"""
    field = get_model_field(BaseImage, "owner")

    self.assertIsInstance(field, models.ForeignKey)
    self.assertEqual(field.rel.to, get_user_model())

【问题讨论】:

我在测试中创建了一个新模型并创建了它的实例,但我没有收到任何错误。 @ChillarAnand 我已经添加了一些代码。你是用 Django 1.7 做到的,然后南关了吗?我仍然得到表不存在:/ 不应该是你的对象被嘲笑而不是那样定义吗? @aRkadeFR 我将如何模拟它以使其工作? 【参考方案1】:

有一张票要求提供一种方法来做只测试模型here

作为一种解决方法,您可以将您的 tests.py 解耦并使其成为一个应用程序。

tests
|--migrations
|--__init__.py
|--models.py
|--tests.py

你会得到这样的结果:

myapp
|-migrations
|-tests
|--migrations
|--__init__.py
|--models.py
|--tests.py
|-__init__.py
|-models.py
|-views.py

那么你应该把它添加到你的INSTALLED_APPS

INSTALLED_APPS = (
    # ...
    'myapp',
    'myapp.tests',
)

您可能不想在生产环境中安装myapp.tests,因此您可以保留单独的设置文件。像这样的:

INSTALLED_APPS = (
    # ...
    'myapp',
)

try:
    from local_settings import *
except ImportError:
    pass

或者更好的是,创建一个测试运行器并在那里安装您的测试。

最后但同样重要的是,记得运行python manage.py makemigrations

【讨论】:

此解决方案会导致测试模型作为表存在于生产数据库中,对吗?这是不可接受的。 不,答案表明使用单独的设置文件进行测试与生产,以避免在生产中创建测试模型。【参考方案2】:

这是一个似乎可行的解决方法。诱使迁移框架认为您的应用程序没有迁移。在settings.py:

if 'test' in sys.argv:
    # Only during unittests...

    # myapp uses a test-only model, which won't be loaded if we only load
    # our real migration files, so point to a nonexistent one, which will make
    # the test runner fall back to 'syncdb' behavior.
    MIGRATION_MODULES = 
        'myapp': 'myapp.migrations_not_used_in_tests'
    

我在first post in ths Django dev mailing list thread 上找到了这个想法,它目前也在Django itself 中使用,但它可能不适用于需要迁移并且删除“syncdb fallback”的未来版本的 Django。

【讨论】:

以上是关于测试中的模型 - Django 1.7 问题的主要内容,如果未能解决你的问题,请参考以下文章

Django 1.7 中的 Django-migrations 检测模型更改,但不会在迁移时应用它们

在迁移中获取模型 ContentType - Django 1.7

Django 1.7 中的迁移

Django 1.7(显然)没有在 manage.py 测试中运行迁移

Django 1.7 - 具有自定义应用标签的模型发现和应用配置

Django-多态模型在1.7上进行迁移时遇到问题