Разные БД для тестирования в Django?

41
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 для модульных тестов, так как это отлично работает.)

  • 1
    Вы пробовали, действительно ли у пользователя postgres есть права на создание базы данных?
  • 0
    Этот пользователь postgres работает для обычного просмотра сайта, но я не уверен, что он может создать БД.
Показать ещё 1 комментарий
Теги:
unit-testing

6 ответов

50
Лучший ответ

В settings.py (или local_settings.py):

import sys
if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase'
    }
  • 4
    это может быть хакерским, но это работает.
  • 6
    @Rosarch ... да; это немного "нахально", но вы правы! Оно работает. :) Но, ИМХО, наличие какой-либо базы данных для тестирования UNIT является хакерским. Я бы хотел, чтобы у Джанго была другая философия, когда дело дошло до этого.
Показать ещё 3 комментария
22

То, как я справляюсь с этим, - это наличие нескольких файлов настроек, поскольку я использую это для поддержки набора общих настроек с изменениями для каждого экземпляра. Это немного сложнее настроить, чем некоторые другие решения, но мне все равно пришлось это сделать, потому что я управлял небольшими настройками для локального развития, удаленного развития, постановки и производства.

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

Общие настройки находятся в настройках /defaults.py, и я импортирую их в файлы настроек экземпляра. Поэтому настройки /unittest.py выглядят следующим образом:

from defaults import *

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

Затем, когда я хочу запускать тесты, я просто выполняю:

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

использовать sqlite для тестирования. Я буду использовать другой модуль настроек, если я хочу использовать другой тестовый бегун или конфигурацию базы данных.

  • 0
    Как человек с опытом работы с Rails, я нашел этот ответ лучшим. Rails использует тот же тип соглашения, с небольшим отличием, что в Rails каталог настроек называется config.
6

Это ускорило резкое выполнение теста.

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
3

Хотя это уже решено...

Если ваша база данных для тестов является обычным DB:

Я думаю, что вы не делаете unit test, поскольку вы полагаетесь на базу данных. В любом случае, django содержит тестовый тип для этого (не унитарный): django.test.TestCase

Вы должны получить django.test.TestCase вместо unittest.TestCase, который создаст для вас новую базу данных rehershal, которая будет уничтожена при завершении тестирования.

Есть интересные объяснения/советы по тестированию с помощью db в следующей ссылке
Тестирование приложений Django

  • 0
    Проблема, с которой я иногда сталкиваюсь, заключается в том, что живые данные довольно сложны и получены из какого-то внешнего источника. Для тестирования я хочу подмножество. Да, я мог бы создать это подмножество - это настройка моего тестового класса. Но это может быть нетривиально. Особенно мне лучше, если мои тесты доступны только для чтения в отношении БД.
  • 0
    Тогда у вас будет потенциально невоспроизводимый тест: $ и для выполнения ваших тестов потребуется подключение к открытому миру.
3

Если у вас есть доступ к созданию базы данных вручную, вы можете использовать django-nose как ваш TEST_RUNNER. После установки, если вы передадите следующую переменную среды, она не удалит и не заново создаст базу данных.

REUSE_DB=1 ./manage.py test

Вы также можете добавить следующее в settings.py, чтобы вам не приходилось писать REUSE_DB = 1 каждый раз, когда вы хотите запускать тесты:

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

Примечание. это также оставит все ваши таблицы в базах данных, что означает, что установка теста будет немного быстрее, но вам придется вручную обновлять таблицы (или удалять и воссоздавать базу данных самостоятельно), когда вы меняете свои модели.

0

Почему я могу получить эту ошибку?

Из-за недостаточных разрешений. Вы можете изменить права пользователя на ALTER USER username CREATEDB; после запуска psql с привилегиями суперпользователя.

Пример

$ sudo su - postgres
$ psql
psql (9.3.18)
Type "help" for help.

postgres=# ALTER USER username CREATEDB;
ALTER ROLE

Ещё вопросы

Сообщество Overcoder
Наверх
Меню