首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何跳过Django中一个测试数据库的创建

如何跳过Django中一个测试数据库的创建
EN

Stack Overflow用户
提问于 2018-06-27 21:02:21
回答 2查看 1.5K关注 0票数 3

我们在Django应用程序中使用了两个数据库,一个是“事务性”数据库,另一个是“分析型”数据库(用作数据仓库)。“事务性”一个使用django模型创建,“分析”一个使用我们的自定义脚本创建,其中包含“事务性”表的多个联接的原始sql。

当我们为django应用程序运行测试时,两个数据库都创建了相应的测试版本,比如"test_transactional“和"test_analytical”。创建"test_transactional“是可以的,但是我们希望跳过"test_analytical”的创建,因为这个创建将由我们的自定义脚本来创建和填充。

jenkins日志中的片段:

代码语言:javascript
运行
复制
python manage.py test --keepdb cis.tests.test_views --  
noinput --settings=strainprint.settings.local --verbosity=2
...
Using existing test database for alias 'analytics' 
('test_strainprint_analytics')...
...
Synchronizing apps without migrations:
Creating tables...
Creating table django_admin_log
Creating table auth_permission
...

在Django有办法做到这一点吗?我们使用django 1.10。

EN

回答 2

Stack Overflow用户

发布于 2018-11-27 00:26:03

按照要求,下面是我最后实现的内容。这里的“遗留”数据库是一个我们希望跳过创建的数据库--Django应该假设它已经存在了。

您首先需要添加这个稍微修改过的测试运行程序,project/runner.py

代码语言:javascript
运行
复制
from django.test.runner import DiscoverRunner
from django.test.utils import get_unique_databases_and_mirrors
from django.db import connections


class LegacyDatabaseRunner(DiscoverRunner):
    """
    Test runner that will skip attempting to create any database with LEGACY=True
    in its TEST configuration dictionary
    """
    def setup_databases(self, **kwargs):
        return _setup_databases(
            self.verbosity, self.interactive, self.keepdb, self.debug_sql,
            self.parallel, **kwargs
        )


def _setup_databases(verbosity, interactive, keepdb=False, debug_sql=False, parallel=0, **kwargs):
    """Clone of django.test.utils.setup_databases"""
    test_databases, mirrored_aliases = get_unique_databases_and_mirrors()

    old_names = []

    for db_name, aliases in test_databases.values():
        first_alias = None
        for alias in aliases:
            connection = connections[alias]

            # This clause is all that's been added. If the database's TEST configuration
            # has LEGACY=True, skip attempting to create the database, and don't add it
            # to the list of databases to tear down after testing is complete.
            if connection.settings_dict.get('TEST', {}).get('LEGACY', False):
                continue

            old_names.append((connection, db_name, first_alias is None))

            # Actually create the database for the first connection
            if first_alias is None:
                first_alias = alias
                connection.creation.create_test_db(
                    verbosity=verbosity,
                    autoclobber=not interactive,
                    keepdb=keepdb,
                    serialize=connection.settings_dict.get('TEST', {}).get('SERIALIZE', True),
                )
                if parallel > 1:
                    for index in range(parallel):
                        connection.creation.clone_test_db(
                            suffix=str(index + 1),
                            verbosity=verbosity,
                            keepdb=keepdb,
                        )
            # Configure all other connections as mirrors of the first one
            else:
                connections[alias].creation.set_as_test_mirror(connections[first_alias].settings_dict)

    # Configure the test mirrors.
    for alias, mirror_alias in mirrored_aliases.items():
        connections[alias].creation.set_as_test_mirror(
            connections[mirror_alias].settings_dict)

    if debug_sql:
        for alias in connections:
            connections[alias].force_debug_cursor = True

    return old_names

接下来,让它成为project/settings.py中的默认运行程序。

代码语言:javascript
运行
复制
TEST_RUNNER = 'project.runner.LegacyDatabaseRunner'

然后在设置中使用LEGACY=True标记任何要跳过创建的数据库:

代码语言:javascript
运行
复制
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': ...,
        },
        'legacy_db1': {
            'ENGINE': 'sql_server.pyodbc',
            'NAME': ...,
            'TEST': {
                'LEGACY': True,  # Do not manage this database during tests
            },
        },
    }

那么,希望运行manage.py test能像预期的那样工作。

请注意,在运行并行测试时,这将不起作用。我在这方面取得了一些进展,我修补了ParallelTestSuite.init_worker,并对setup_databases做了更多修改,但它还没有完全发挥作用。

旧的答案,可能会在紧要关头起作用

这并不是一种特别安全的方法,因为这个配置选项的语义可能会改变,但是您可以声明一个数据库是另一个数据库的“副本”:

代码语言:javascript
运行
复制
DATABASES = {
    'default': {
        'NAME': 'transactional',
         ...
    },
    'analytical': {
        'NAME': 'analytical',
        ...
        'TEST': {
            'MIRROR': 'default',
        },
    }
}

MIRROR配置选项记录在这里:https://docs.djangoproject.com/en/dev/topics/testing/advanced/#testing-primary-replica-configurations

相关的Django在这里:https://github.com/django/django/blob/master/django/test/utils.py

票数 4
EN

Stack Overflow用户

发布于 2022-06-06 18:32:55

我没有得到一个忽略第一个数据库创建的解决方案,但是如果所有迁移都已在其上创建,则可以重用现有的数据库。

通常,我使用以下设置使用pytest执行Django测试:

注意最后一个字段:附加参数。

它的价值是:--exitfirst --reuse-db。在这个附加的arg中使用pytest也可以在命令行上工作,但是我更喜欢使用PyCham,因为有了调试器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51071355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档