【问题标题】:Different db for testing in Django?用于在 Django 中进行测试的不同数据库?
【发布时间】:2011-06-06 17:40:04
【问题描述】:
DATABASES = {
#    'default': {
#        'ENGINE': 'postgresql_psycopg2',
#        ...
#    }

    # for unit tests
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase'
    }
}

我有两个数据库:一个用于单元测试,一个用于其他所有方面。是否可以在 Django 1.2.4 中进行配置?

(我问的原因是因为使用 postgresql 我收到以下错误:

foo@bar:~/path/$ python manage.py test
Creating test database 'default'...
Got an error creating the test database: permission denied to create database

Type 'yes' if you would like to try deleting the test database 'test_baz', or 'no' to cancel: yes
Destroying old test database...
Got an error recreating the test database: database "test_baz" does not exist

为什么我会收到此错误?我想我真的不在乎我是否总是可以使用 SQLite 进行单元测试,因为它工作得很好。)

【问题讨论】:

  • 你试过postgres用户是否真的有数据库创建权限?
  • 那个postgres用户可以正常浏览网站,但我想我不确定它是否可以创建数据库。
  • 就像@CarlesBarrobés 所说,您可能没有 CREAETE 权限。这直接来自 django 的文档:请注意,要使用此功能,Django 正在连接的数据库用户必须具有 CREATE DATABASE 权限。

标签: django unit-testing sqlite postgresql


【解决方案1】:

在您的settings.py(或local_settings.py)中:

import sys
if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase'
    }

【讨论】:

  • @Rosarch... 是的;这有点“hacky”,但你是对的!有用。 :) 但是,恕我直言,必须拥有任何用于 UNIT 测试的数据库是不合时宜的。我希望 Django 在这方面有不同的理念。
  • @sleepycal 为什么会这样?
  • 我正在尝试使用此解决方案,但我想使用 Postgres 作为测试数据库引擎,但我收到一条错误消息,指出表不存在。我认为测试创建了数据库。是这样吗?
  • @HuLuViCa 您使用托管还是非托管模型?你在使用运行脚本吗?
【解决方案2】:

我处理这个问题的方法是拥有多个设置文件,因为我使用它来维护一组通用设置,并对每个实例进行修改。与其他一些解决方案相比,它的设置稍微复杂一些,但我还是需要这样做,因为我为本地开发、远程开发、登台和生产管理的设置略有不同。

https://code.djangoproject.com/wiki/SplitSettings 有许多用于管理设置的选项,我选择了一种类似于https://code.djangoproject.com/wiki/SplitSettings#SimplePackageOrganizationforEnvironments 中描述的做法

所以,在我的 Django 项目目录中,我有一个如下所示的设置文件夹:

$ tree settings
settings
├── defaults.py
├── dev.py
├── dev.pyc
├── __init__.py
├── lettuce.py
├── travis.py
├── unittest.py

常用设置在 settings/defaults.py 中,我将它们导入到我的实例设置文件中。所以 settings/unittest.py 看起来像这样:

from defaults import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'my_database',
    }
} 

然后,当我想运行测试时,我只需执行:

$ ./manage.py test --settings=settings.unittest

使用 sqlite 进行测试。如果我想使用不同的测试运行器或数据库配置,我将使用不同的设置模块。

【讨论】:

  • 作为具有 Rails 背景的人,我发现这个答案是最好的。 Rails 使用相同的约定,只是在 Rails 中设置目录名为 config.
【解决方案3】:

您可以在settings.py 中指定测试数据库。看 https://docs.djangoproject.com/en/3.0/topics/testing/overview/#the-test-database

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'mydatabaseuser',
        'NAME': 'mydatabase',
        'TEST': {
            'NAME': 'mytestdatabase',
        },
    },
}

【讨论】:

  • 这是一个完美运行的简单解决方案。我正在使用 pythonanywhere 网站,这让我可以运行教程。
  • 这可以让我更换引擎吗?
  • @Zee 是的,你可以改变我的想法。查看文档以获取更多信息docs.djangoproject.com/en/2.0/topics/testing/overview/…
  • 很遗憾,您无法更改HOST
  • 这可行,但请注意default 仍然需要解决。例如,如果在运行测试时无法解析数据库的 URL,则测试将崩溃。
【解决方案4】:

这大大加快了测试的执行速度。

import sys

if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'TEST_CHARSET': 'UTF8', # if your normal db is utf8
        'NAME': ':memory:', # in memory
        'TEST_NAME': ':memory:', # in memory
    }

    DEBUG = False # might accelerate a bit
    TEMPLATE_DEBUG = False

    from django.core.management import call_command
    call_command('syncdb', migrate=True) # tables don't get created automatically for me

【讨论】:

    【解决方案5】:

    我解决了这个问题,只需创建其他设置常量DATABASES_AVAILABLE

    DATABASES_AVAILABLE = {
        'main': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'nep',
            'USER': 'user',
            'PASSWORD': 'passwd',
            'HOST': 'localhost',
        },
        'remote': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'nes_dev',
            'USER': 'usr',
            'PASSWORD': 'passwd',
            'HOST': '200.144.254.136',
        },
        'sqlite': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        },
    }
    
    # This solves the problem with tests
    # Define a system variable called DJANGO_DATABASE_TEST and set it to the
    # the database you want
    database = os.environ.get('DJANGO_DATABASE_TEST', 'main')
    DATABASES = {
        'default': DATABASES_AVAILABLE[database]
    }
    

    【讨论】:

      【解决方案6】:

      虽然这已经解决了……

      如果你的测试数据库只是一个普通的数据库:

      我认为您没有进行单元测试,因为您依赖于数据库。无论如何,django 包含一个测试类型(不是单一的):django.test.TestCase

      您需要派生自 django.test.TestCase 而不是 unittest.TestCase,这将为您创建一个新的 rehershal 数据库,该数据库将在测试结束时被销毁。

      以下链接中有关于使用 db 进行测试的有趣解释/提示
      Testing Django Applications

      【讨论】:

      • 我有时遇到的问题是实时数据相当复杂并且来自某些外部来源。为了测试我想要一个子集。是的,我可以创建该子集是我的测试类设置。但它可能不是微不足道的。如果我的测试就数据库而言是只读的,我特别发现它会更好。
      • 然后您可能会有不可重现的测试:$ 并且运行您的测试将需要连接到开放世界
      【解决方案7】:

      如果您有权手动创建数据库,则可以使用django-nose 作为您的 TEST_RUNNER。安装后,如果传递以下环境变量,不会删除并重新创建数据库。

      REUSE_DB=1 ./manage.py test
      

      您还可以将以下内容添加到 settings.py 中,这样您就不必每次要运行测试时都编写 REUSE_DB=1:

      os.environ['REUSE_DB'] = "1"
      

      注意:这也会将您的所有表格留在数据库中,这意味着测试设置会更快一些,但您必须手动更新表格(或更改模型时自行删除并重新创建数据库。

      【讨论】:

        【解决方案8】:

        你可以通过编辑settings.py来镜像你的数据库:

        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.postgresql',
                'USER': 'mydatabaseuser',
                'NAME': 'mydatabase',
                'TEST': {
                    'MIRROR': 'default',
                },
            },
        }
        

        【讨论】:

        • 这应该是公认的答案,不仅适用于这个问题,而且适用于大多数涉及在 Django 中执行涉及数据库访问的单元测试的问题。今天我花了 5 个小时在谷歌上搜索并阅读了很多博客文章。他们都很老套,晦涩难懂。这是唯一一个真正的 Pythonic,利用 Django 的默认设置并涵盖大多数用例。谢谢@ForeverOpp
        【解决方案9】:

        为什么会出现这个错误?

        因为权限不足。在以超级用户权限运行psql 后,您可以通过ALTER USER username CREATEDB; 更改用户权限。

        例子,

        $ sudo su - postgres
        $ psql
        psql (9.3.18)
        Type "help" for help.
        
        postgres=# ALTER USER username CREATEDB;
        ALTER ROLE
        

        【讨论】:

          猜你喜欢
          • 2020-06-19
          • 2022-08-02
          • 2018-09-12
          • 2018-03-25
          • 1970-01-01
          • 2014-07-17
          • 2015-12-15
          • 2019-04-18
          • 2023-03-03
          相关资源
          最近更新 更多