在Django中使用动态数据库TEST_NAME是危险的吗?

时间:2013-11-22 03:00:10

标签: django testing jenkins

我们是一个使用PostgreSQL数据库后端处理应用程序的开发人员团队。我们每个人都有一个单独的工作目录和virtualenv,但我们共享相同的PostgreSQL数据库服务器,甚至Jenkins也在同一台机器上。

因此,我试图想出一种方法,允许我们在同一个项目上并行运行测试,而不会遇到数据库名称冲突。此外,有时Jenkins构建会在中途失败并且测试数据库最终不会被丢弃,这样后续的Jenkins构建可能会被现有数据库混淆并自动失败。

我决定尝试的是:

import os
from datetime import datetime

DATABASES = {
    'default': {
        # the usual lines ...
        TEST_NAME: '{user}_{epoch_ts}_awesome_app'.format(
            user=os.environ.get('USER', os.environ['LOGNAME']),
            # This gives the number of seconds since the UNIX epoch
            epoch_ts=int((datetime.utcnow() - datetime.utcfromtimestamp(0)).total_seconds())
        ),
        # etc
    }
}

因此,使用用户名和时间戳,每次测试运行最可能的测试数据库名称将是唯一的。通过这种方式,我认为Jenkins甚至可以并行运行构建。

到目前为止似乎有效。但它有危险吗?我猜我们是安全的,只要我们不尝试直接导入项目设置模块并且只使用django.conf.settings,因为应该类似单身并仅评估一次,正确?

2 个答案:

答案 0 :(得分:1)

我正在做类似的事情并没有遇到任何问题。应采取通常的预防措施:

  1. 请勿直接访问settings

  2. 不要导致settings中的值在模块的顶层进行评估。有关详细信息,请参阅doc。例如,不要这样做:

    from django.conf import settings
    
    # This is bad because settings might still be in the process of being
    # configured at this stage.
    blah = settings.BLAH
    
    def some_view():
        # This is okay because by the time views are called by Django, 
        # the settings are supposed to be all configured.
        blah = settings.BLAH
    
  3. 不要在模块的顶层访问数据库。 doc警告:

      

    如果您的代码在编译模块时尝试访问数据库,则会在设置测试数据库之前进行,这可能会产生意外结果。例如,如果您在模块级代码中有数据库查询并且存在真实数据库,则生产数据可能会污染您的测试。无论如何在代码中都有这样的导入时数据库查询是一个坏主意 - 重写代码以便它不会这样做。

答案 1 :(得分:0)

您可以使用Jenkins执行程序编号(在环境中可用)而不是时间;这将是足够独特的,你不必担心它会改变。

作为奖励,您可以使用--keepdb来避免每次从头开始重建数据库......在缺点方面,必须单独删除失败和损坏的数据库(也许settings.py可以打印出来它使用的数据库名称,以方便手动删除。