2015-10-30 6 views
19

Ho un'applicazione Django che utilizza 2 connessioni al database:Django ignora il router durante l'esecuzione dei test?

  1. di connettersi ai dati effettivi dell'app è quello di produrre
  2. Per un sistema master data di riferimento, che viene portato avanti completamente al di fuori del mio controllo

Il problema che sto riscontrando è che la mia webapp NON può assolutamente toccare i dati nel 2 ° database. Ho risolto la maggior parte dei problemi utilizzando 2 (sotto) app, una per ogni connessione al database. Ho creato un file di router che router qualsiasi migrazione, e la scrittura per la prima applicazione

Ho fatto anche tutti i modelli della seconda applicazione non gestiti, utilizzando l'opzione

model.meta.managed = False 

.

A dire il vero, l'utente si collega al database è 2 ° accesso in sola lettura

Questo funziona bene per le migrazioni e l'esecuzione. Tuttavia, quando provo a eseguire i test utilizzando la django testcase, Django tenta di eliminare e creare un database test_ sulla seconda connessione al database.

Come posso fare in modo che Django sarà MAI aggiornare/delete/insert/drop/troncare sopra il 2 ° collegamento

Come posso eseguire test, che non cercano di creare il secondo database, ma fare crea il primo

Grazie!

Modificato: codice

modello (per il 2 ° app, che non dovrebbe essere gestito):

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' 

... 

router:

__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 

impostazioni:

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'), 
    }, 
} 

un TestCase:

from django.test.testcases import TestCase 

__author__ = 'CoesseWa' 


class ModelTest(TestCase): 

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

uscita dal momento in cui l'esecuzione di questo test:

... 
Destroying old test user... 

(prima di questo punto, Django crea il database di prova per la mia prima connessione = OK)

Creating test user... 

=> Le righe successive non dovrebbero mai accadere.Fallisce perché io uso un unico utente lettura (per fortuna)

Creating test database for alias 'mdm_db'... 

Failed (ORA-01031: insufficient privileges 
Got an error creating the test database: ORA-01031: insufficient privileges 
+0

Mi piacerebbe vedere più codice, puoi mostrare i tuoi test e le modelle? – Uri

risposta

10

Ho risolto questo problema modificando la definizione DATABASES.TEST. Ho aggiunto TEST['MIRROR'] = 'default' alla voce del database 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 
     } 
    }, 
} 

Secondo l'documentation questa opzione può essere abusata per saltare la creazione database:

Tuttavia, il database di replica è stato configurato come uno specchio di prova (utilizzando l'impostazione test dello specchio), indicando che in fase di test, la replica deve essere considerata come un mirror di default.

Quando l'ambiente di prova è configurato, non verrà creata una versione di prova della replica . Invece la connessione alla replica sarà reindirizzata al punto di default.

L'esecuzione dei test ora salta la creazione del secondo database.

Grazie per tutto l'input !!

+0

grazie mille! questo ha aiutato così tanto! – TheLuminor

2

Utilizzare il flag --settings con il comando test. Nel modulo path.to.test.py, a la python manage.py test --settings=app.settings.test. Non è necessario andare in giro con le rotte, ma assicurati di invocare i test con il flag delle impostazioni quando e dove mai lo chiami.

In app.settings.test.py, ridefinire i database datastructure:

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

Questo consente di utilizzare un database separato durante l'esecuzione di test. Inoltre, se si utilizza sqlite3 come motore, si scoprirà che i test vengono eseguiti molto velocemente mentre il database è in memoria.

L'utilizzo di database sqlite3 per i test consente di eseguire anche centinaia di test in pochi secondi. Di conseguenza, è possibile eseguire i test molto frequentemente. Di solito mappo una chiave per salvare il mio lavoro ed eseguo i miei test con una sola azione:

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

Spero che sia utile!

+0

Sto usando un file di impostazioni diverso ... Il problema è che non posso praticamente copiare sul secondo database sul mio computer locale per eseguire i test. Il contenuto del database secondario è in qualche modo parte della logica, quindi ho bisogno di verificare che la mia app funzioni correttamente. – Ward

+0

Puoi usare i metodi setUp e tearDown dei tuoi TestCase per creare oggetti su cui puoi testare. Non sono sicuro che sia particolarmente utile, ma potrebbe essere qualcosa che vale la pena guardare. –