6

我正在尝试为我的 django 项目编写测试用例,但是当我运行“$ ./manage.py test”命令时,它正在创建测试数据库,但它没有创建任何表,并且我收到表不存在的错误。欢迎任何建议。这是我通过“./manage.py inspectdb > models.py”创建的模型

class MyCustomModel(models.Model):
    name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)

    class Meta:
       managed = False
       db_table = 'MY_TABLE'
4

4 回答 4

8

pytest 在测试期间为非托管模型创建表

--nomigrations添加到您的pytest.inisetup.cfg- 无论您的 pytest 设置所在的位置:

[pytest]
addopts = --nomigrations

并将其添加到您的顶级conftest.py

@pytest.fixture(autouse=True, scope="session")
def django_test_environment(django_test_environment):
    from django.apps import apps

    get_models = apps.get_models

    for m in [m for m in get_models() if not m._meta.managed]:
        m._meta.managed = True

它会变魔术

于 2018-06-14T03:07:33.540 回答
7

您的表是非托管的 ( managed = False),因此它不会在迁移或测试期间自动创建。

  1. 如果您的表应该在迁移期间创建,只需删除该managed = False
  2. 如果您的表是不应在迁移期间创建的视图或旧表,则需要在测试期间管理模型。

如果 2,并且您使用的是 simple manage.py test,我发现的最佳解决方案是添加一个测试运行程序,该运行程序可以修改任何非托管模型上的托管标志。我的在 runners.py 文件中看起来像这样:

# Credit:
# http://birdhouse.org/blog/2015/03/25/django-unit-tests-against-unmanaged-databases/
# https://www.caktusgroup.com/blog/2010/09/24/simplifying-the-testing-of-unmanaged-database-models-in-django/

from smapi.settings import *
from django.test.runner import DiscoverRunner


class ManagedModelTestRunner(DiscoverRunner):
    """
    Test runner that automatically makes all unmanaged models in your Django
    project managed for the duration of the test run, so that one doesn't need
    to execute the SQL manually to create them.
    """

    def __init__(self, **kwargs):
        from django.apps import apps

        super(ManagedModelTestRunner, self).__init__(**kwargs)

        # for a in apps.get_apps():
        #     print("Found app %s" % (a))

        # NOTE: apps must be registered in INSTALLED_APPS in settings.py before their models appear here
        all_models = apps.get_models()
        # for m in all_models:
        #     print("Found model %s - Managed:%s" % (m, m._meta.managed))

        self.unmanaged_models = [m for m in all_models if not m._meta.managed]

    def setup_test_environment(self, *args, **kwargs):
        for m in self.unmanaged_models:
            m._meta.managed = True
            # print("Modifying model %s to be managed for testing - Managed:%s" % (m, m._meta.managed))
        super(ManagedModelTestRunner, self).setup_test_environment(*args, **kwargs)

    def teardown_test_environment(self, *args, **kwargs):
        super(ManagedModelTestRunner, self).teardown_test_environment(*args, **kwargs)
        # reset unmanaged models
        for m in self.unmanaged_models:
            m._meta.managed = False
            # print("Resetting model %s to be unmanaged - Managed:%s" % (m, m._meta.managed))

通过将此行添加到 settings.py 来激活它:

# Set Django's test runner to the custom class defined in runners.py
TEST_RUNNER = '<project name>.runners.ManagedModelTestRunner'

最后,我今天来到这里是因为我们开始使用 pytest 进行测试,而上面的解决方案停止了工作。经过大量搜索,我在上面示例中的一个页面的评论中发现了一个修复(来源,归功于 Jan Murre

谢谢你的把戏。因为我使用的是 pytest-django,所以我必须找出如何以我的方式做到这一点。

pytest-django 使用固定装置。已经有一个夹具可以执行 setup_test_environment() 调用。

因此,我们需要一个在此之前的夹具来设置“_meta.managed”。似乎自动夹具是按字母顺序执行的,所以在 pytest-django 夹具(名称以“_django”开头)之前,我们的夹具名称以“__”开头。

@pytest.fixture(autouse=True, scope='session')
def __make_unmanaged_managed():
    from django.db.models.loading import get_models
    unmanaged_models = [m for m in get_models() if not m._meta.managed]
    for m in unmanaged_models:
        m._meta.managed = True

我们将上面的代码放在 conftest.py 中,我们的测试又开始工作了。

于 2016-07-07T15:58:32.473 回答
0

你有迁移吗?Run python manage.py makemigrations,在测试运行期间构建的数据库使用它们。

于 2015-06-23T14:31:12.903 回答
0

你需要使用:

./manage.py syncdb

这是替换为

./django-admin migrate

从 django 1.7

于 2015-06-23T14:59:59.163 回答