简体   繁体   English

测试中的模型 - Django 1.7问题

[英]Models inside tests - Django 1.7 issue

I'm trying to port my project to use Django 1.7. 我正在尝试移植我的项目以使用Django 1.7。 Everything is fine except 1 thing. 一切都很好,除了一件事。 Models inside tests folders. 测试文件夹内的模型。

Django 1.7 new migrations run migrate command internally. Django 1.7新迁移在内部运行migrate命令。 Before syncdb was ran. 在syncdb运行之前。 That means if a model is not included in migrations - it won't be populated to DB (and also to test DB). 这意味着如果模型未包含在迁移中 - 它将不会填充到DB(以及测试数据库)。 That's exactly what I'm experiencing right now. 这正是我现在所经历的。

What I do is: 我所做的是:

In my /app/tests/models.py I have dummy model: class TestBaseImage(BaseImage): pass All it does is to inherit from an abstract BaseImage model. 在我的/app/tests/models.py我有一个虚拟模型: class TestBaseImage(BaseImage): pass它所做的只是从一个抽象的 BaseImage模型继承。

Then in tests I create instances of that dummy model to test it. 然后在测试中我创建该虚拟模型的实例来测试它。

The problem is that it doesn't work any more. 问题是它不再起作用了。 It's not included in migrations (that's obvious as I don't want to keep my test models in a production DB). 它不包含在迁移中(这很明显,因为我不想将我的测试模型保存在生产数据库中)。 Running my tests causes DB error saying that table does not exist . 运行我的测试会导致数据库错误,表明该table does not exist That makes sense as it's not included in migrations. 这是有道理的,因为它不包含在迁移中。

Is there any way to make it work with new migrations system? 有没有办法让它适用于新的迁移系统? I can't find a way to "fix" that. 我找不到一种“修复”的方法。

Code I use: 我使用的代码:

app/tests/models.py 应用程序/测试/ models.py

from ..models import BaseImage


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

app/models.py 应用程序/ models.py

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

factories: 工厂:

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


class PortImageFactory(BaseImageFactory):
    FACTORY_FOR = PortImage

example test: 示例测试:

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

There is a ticket requesting a way to do test-only models here 有一张票要求在这里进行仅测试模型的方法

As a workaround, you can decouple your tests.py and make it an app. 作为一种解决方法,您可以将tests.py解耦并使其成为应用程序。

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

You will end up with something like this: 你最终会得到这样的东西:

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

Then you should add it to your INSTALLED_APPS 然后你应该把它添加到你的INSTALLED_APPS

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

You probably don't want to install myapp.tests in production, so you can keep separate settings files. 您可能不希望在生产中安装myapp.tests ,因此您可以保留单独的设置文件。 Something like this: 像这样的东西:

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

try:
    from local_settings import *
except ImportError:
    pass

Or better yet, create a test runner and install your tests there. 或者更好的是,创建一个测试运行器并在那里安装测试。

Last but not least, remember to run python manage.py makemigrations 最后但同样重要的是,请记住运行python manage.py makemigrations

Here's a workaround that seems to work. 这是一个似乎有效的解决方法。 Trick the migration framework into thinking that there are no migrations for your app. 欺骗迁移框架,认为您的应用没有迁移。 In settings.py : 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'
    }

I found the idea on the first post in ths Django dev mailing list thread , and it's also currently being used in Django itself , but it may not work in future versions of Django where migrations are required and the "syncdb fallback" is removed. 在Django dev邮件列表线程第一篇文章中找到了这个想法,它目前也在Django本身使用 ,但它可能不适用于需要迁移并删除“syncdb fallback”的Django的未来版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM