Подтвердить что ты не робот

Django игнорирует маршрутизатор при выполнении тестов?

У меня есть приложение django, которое использует 2 подключения к базе данных:

  • Чтобы подключиться к фактическим данным, приложение должно создавать
  • В справочную систему основных данных, которая поддерживается полностью вне моего контроля

Проблема, с которой я столкнулась, заключается в том, что мой webapp не может абсолютно НЕ касаться данных во второй базе данных. Я решил большинство проблем, используя 2 (югу) приложения, по одному для каждого подключения к базе данных. Я создал файл-маршрутизатор, который переносит любую миграцию и записывает в первое приложение

Я также сделал все модели во втором приложении не управляемыми, используя

model.meta.managed = False

вариант.

Конечно, пользователь, подключенный ко второй базе данных, имеет доступ только для чтения

Это отлично подходит для миграции и работы. Однако, когда я пытаюсь запустить тесты с помощью тестового теста django, Django пытается удалить и создать базу данных test_ во втором подключении базы данных.

Как я могу убедиться, что Django никогда не будет обновлять/удалять/вставлять/удалять/обрезать по второму соединению

Как запустить тесты, которые не пытаются создать вторую базу данных, но создать первый.

Спасибо!

отредактирован: code

(для второго приложения, которое не должно управляться):

from django.db import models


class MdmMeta(object):
    db_tablespace = 'MDM_ADM'
    managed = False
    ordering = ['name']


class ActiveManager(models.Manager):
    def get_queryset(self):
        return super(ActiveManager, self).get_queryset().filter(lifecyclestatus='active')


class MdmType(models.Model):
    entity_guid = models.PositiveIntegerField(db_column='ENTITYGUID')
    entity_name = models.CharField(max_length=255, db_column='ENTITYNAME')

    entry_guid = models.PositiveIntegerField(primary_key=True, db_column='ENTRYGUID')

    name = models.CharField(max_length=255, db_column='NAME')
    description = models.CharField(max_length=512, db_column='DESCRIPTION')

    lifecyclestatus = models.CharField(max_length=255, db_column='LIFECYCLESTATUS')

    # active_manager = ActiveManager()

    def save(self, *args, **kwargs):
        raise Exception('Do not save MDM models!')

    def delete(self, *args, **kwargs):
        raise Exception('Do not delete MDM models!')

    def __str__(self):
        return self.name

    class Meta(MdmMeta):
        abstract = True


# Create your models here.
class MdmSpecies(MdmType):
    class Meta(MdmMeta):
        db_table = 'MDM_SPECIES'
        verbose_name = 'Species'
        verbose_name_plural = 'Species'


class MdmVariety(MdmType):
    class Meta(MdmMeta):
        db_table = 'MDM_VARIETY'
        verbose_name = 'Variety'
        verbose_name_plural = 'Varieties'

...

маршрутизатор:

__author__ = 'CoesseWa'

class MdmRouter(object):

    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'mdm':
            # return 'default'
            return 'mdm_db'   # trying to use one database connection
        return 'default'

    def db_for_write(self, model, **hints):
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        return None

    def allow_migrate(self, db, model):
        if model._meta.app_label == 'mdm':
            return False

Параметры:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=1521)))(CONNECT_DATA=(SID=%s)))'
                % (get_env_variable('LIMS_MIGRATION_HOST'), get_env_variable('LIMS_MIGRATION_SID')),
        'USER': 'LIMS_MIGRATION',
        'PASSWORD': get_env_variable('LIMS_MIGRATION_PASSWORD'),
    },
    'mdm_db': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=GB3P)(PORT=1521)))'
                '(CONNECT_DATA=(SID=GB3P)))',
        'USER': 'MDM',
        'PASSWORD': get_env_variable('MDM_DB_PASSWORD'),
    },
}

один тестовый файл:

from django.test.testcases import TestCase

__author__ = 'CoesseWa'


class ModelTest(TestCase):

    def test_getting_guid_for_mdm_field(self):
        self.assertIsNotNone(1)

вывод при выполнении этих тестов:

... 
Destroying old test user...

(до этого момента django создает тестовую базу для моего первого подключения = ОК)

Creating test user...

= > Следующие строки никогда не должны происходить. Сбой, потому что я использую только для чтения пользователя (к счастью)

Creating test database for alias 'mdm_db'...

Failed (ORA-01031: insufficient privileges 
Got an error creating the test database: ORA-01031: insufficient privileges
4b9b3361

Ответ 1

Я решил это, изменив определение DATABASES.TEST. Я добавил запись TEST['MIRROR'] = 'default' в базу данных mdm_db.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=1521)))(CONNECT_DATA=(SID=%s)))'
                % (get_env_variable('LIMS_MIGRATION_HOST'), get_env_variable('LIMS_MIGRATION_SID')),
        'USER': 'LIMS_MIGRATION',
        'PASSWORD': get_env_variable('LIMS_MIGRATION_PASSWORD'),
    },
    'mdm_db': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=GB3P)(PORT=1521)))'
                '(CONNECT_DATA=(SID=GB3P)))',
        'USER': 'MDM',
        'PASSWORD': get_env_variable('MDM_DB_PASSWORD'),
        'TEST': {
            'MIRROR': 'default',  # Added this setting
        }
    },
}

В соответствии с документацией этот параметр можно злоупотреблять, чтобы пропустить создание базы данных:

Однако база данных реплик была настроена как тестовое зеркало (с использованием настройки теста MIRROR), что указывает на то, что при тестировании, Реплика должна рассматриваться как зеркало по умолчанию.

Когда тестовая среда настроена, тестовая версия реплики не будет создан. Вместо этого соединение с репликой будет перенаправлено в пункт по умолчанию.

Запуск моих тестов теперь пропускает создание второй базы данных.

Спасибо за все входные данные!

Ответ 2

Используйте флаг --settings с помощью команды test. В модуле path.to.test.py, aa python manage.py test --settings=app.settings.test. Не нужно гадать с маршрутами, просто убедитесь, что вы вызываете тесты с помощью значка настроек, когда и когда вы его называете.

В app.settings.test.py переопределите структуру данных DATABASES:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '',
        'USER': '',
        'PASSWORD': '',
    },
    'mdm_db': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '',
        'USER': '',
        'PASSWORD': '',
    },
}

Это позволяет использовать отдельную базу данных при выполнении тестов. Кроме того, если вы используете sqlite3 в качестве своего движка, вы обнаружите, что тесты выполняются очень быстро, поскольку база данных находится в памяти.

Использование баз данных sqlite3 для тестирования означает, что даже сотни тестов могут запускаться в течение нескольких секунд. В результате вы можете запускать свои тесты очень часто. Обычно я нажимаю ключ для сохранения моей работы и запускаю свои тесты одним действием:

map ,t :up\|!python manage.py test --settings=app.settings.test

Надеюсь, что это полезно!

Ответ 3

Вы можете попытаться высмеять соединение со второй базой данных с помощью python mocks? https://pypi.python.org/pypi/mock - теперь часть stdlib в python 3.