测试中的模型 - Django 1.7问题

时间:2014-09-04 15:23:09

标签: python django django-testing django-1.7 django-migrations

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

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

我的工作是:

在我的/app/tests/models.py我有假模型:class TestBaseImage(BaseImage): pass 它所做的就是从抽象 BaseImage模型继承。

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

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

有没有办法让它适用于新的迁移系统?我无法找到一种方法来修复"这一点。

我使用的代码:

应用/测试/ models.py

from ..models import BaseImage


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

应用/ 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())

2 个答案:

答案 0 :(得分:5)

有一张票要求一种方法来进行仅测试模型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

答案 1 :(得分:3)

这是一个似乎有效的解决方法。欺骗迁移框架,认为您的应用没有迁移。在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中使用,但它可能在Django的未来版本中无法运行,其中需要进行迁移并删除“syncdb fallback”