Django 1.8 和鼻子:冲突的模型?

Posted

技术标签:

【中文标题】Django 1.8 和鼻子:冲突的模型?【英文标题】:Django 1.8 and nose: conflicting models? 【发布时间】:2015-12-18 11:27:29 【问题描述】:

我有一个最近升级到 Django 1.8.4 的 Django 应用程序。我正在使用鼻子 1.3.7 和 django-nose 1.4.1 让我的测试运行器运行 200 多个集成和单元测试。由于升级了 Django 和鼻子,我发现我的 12 个测试失败并出现同样的错误:

======================================================================
ERROR: Failure: RuntimeError (Conflicting 'c' models in application 'nose': <class 'account.tests.form_tests.TestAddress'> and <class 'nose.util.C'>.)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/me/venv/myproj/lib/python2.7/site-packages/nose/loader.py", line 523, in makeTest
    return self._makeTest(obj, parent)
  File "/Users/me/venv/myproj/lib/python2.7/site-packages/nose/loader.py", line 568, in _makeTest
    obj = transplant_class(obj, parent.__name__)
  File "/Users/me/venv/myproj/lib/python2.7/site-packages/nose/util.py", line 644, in transplant_class
    class C(cls):
  File "/Users/me/venv/myproj/lib/python2.7/site-packages/django/db/models/base.py", line 311, in __new__
    new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
  File "/Users/me/venv/myproj/lib/python2.7/site-packages/django/apps/registry.py", line 223, in register_model
    (model_name, app_label, app_models[model_name], model))
RuntimeError: Conflicting 'c' models in application 'nose': <class 'account.tests.form_tests.TestAddress'> and <class 'nose.util.C'>.

奇怪的是 form_tests.py 模块甚至没有引用 TestAddress 这实际上是我的“配置文件”模型中的一个类:

# myprof/profile/models.py
class TestAddress(models.Model):
    user = models.OneToOneField(User, primary_key=True, unique=True)
    address_line_1 = models.CharField(max_length=30)
    address_line_2 = models.CharField(max_length=30, null=True, blank=True)
    city = models.CharField(max_length=30)
    region = models.CharField(max_length=30, null=True, blank=True)
    postal_code = models.CharField(max_length=10, null=True, blank=True)
    country = models.ForeignKey('Country')

    class Meta:
        db_table = 'test_address'

    def __unicode__(self):
        return u'%s' % (self.user.username)

当我的测试需要生成 TestAddress 类的实例时,我使用 factory_boy (v. 2.5.2) 工厂:

# utils/factories.py
from profile.models import TestAddress

class UserFactory(factory.django.DjangoModelFactory):
class Meta:
    model = User
username = 'testuser'

class TestAddressFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = TestAddress
    user = factory.SubFactory('utils.factories.UserFactory')
    address_line_1 = '123 Main St.'
    address_line_2 = 'Apt. A'
    city = 'AnyCity'
    region = 'AnyRegion'
    postal_code = '12345'
    country = factory.SubFactory('utils.factories.CountryFactory')

我在鼻子 loader.py 模块中设置断点,并确认 loader 在“profile.models”中看到“TestAddress”。但是,有一个“parent.__name__”变量设置为“account.tests.model_tests”。我有几个问题:

1. Why is this occurring? 
2. Is there a way I can fix it?  
3. Is there some way I can get nose to tell me which tests are resulting in these runtime errors so that I can at least disable them if I can't fix the problem?  

我设置了“--verbosity=2”,但是 不显示失败测试的名称。我浏览了鼻子文档,没有看到任何东西。最坏的情况是,我可以编写一个脚本来单独调用每个测试并在运行之前回显测试名称,但这看起来非常丑陋且耗时。

谢谢。

【问题讨论】:

【参考方案1】:

我刚遇到这个问题,用@nottest 装饰器解决了。

从技术上讲,它适用于文档中的函数,但用它装饰类也可以:

from nose.tools import nottest                                                  
@nottest
class TestAddressFactory(...):
   ...

装饰器所做的只是将带有值True__test__ 添加到它正在装饰的对象中。

def nottest(func):
    """Decorator to mark a function or method as *not* a test
    """
    func.__test__ = False
    return func

【讨论】:

【参考方案2】:

我在将 Django 项目从 1.6 移植到 1.8 并将 django-nose 更新到 1.4.3 时遇到了同样的问题。

似乎在 1.7 以后使用新的DiscoverRunner,django-nose 尝试运行以Test* 开头的所有类作为测试用例,这导致它们在遇到之前被改编成 django-nose 的 django 应用程序在测试模块中。

我设法通过将它们重命名以避免这种命名方案来解决这个问题,例如AdressTestModel

【讨论】:

以上是关于Django 1.8 和鼻子:冲突的模型?的主要内容,如果未能解决你的问题,请参考以下文章

Django 1.8 迁移、自定义用户模型和 Postgres/MySQL 的奇怪问题

将旧 (Django 0.97) 模型数据导入/迁移到 Django 1.8 或更高版本

Django 1.8:删除/重命名数据迁移中的模型字段

在具有所需 ForeignKey 引用的 Django (1.8) 应用程序之间移动模型

在具有所需 ForeignKey 引用的 Django (1.8) 应用程序之间移动模型

在 django 1.8 中将数据从原始用户模型迁移到自定义用户模型