2015-10-30 13 views
19

Ich habe eine django-Anwendung, die zwei Datenbankverbindungen verwendet:Django ignoriert Router, wenn Tests ausgeführt werden?

  1. zu den eigentlichen Daten Um eine Verbindung der App
  2. zu einem Referenzstammdatensystem zu erzeugen, ist, dass völlig außerhalb meiner Kontrolle gehalten wird

Das Problem, das ich habe, ist, dass meine Webapp absolut nicht die Daten in der 2. Datenbank berühren kann. Ich habe die meisten Probleme gelöst, indem ich 2 (Teil-) Apps verwendet habe, eine für jede Datenbankverbindung. Ich habe einen Router-Datei, die jede Migration Router und Schreiben in die erste App

ich auch nicht geschafft, alle Modelle in der 2. app gemacht, die

model.meta.managed = False 

Option.

Um sicher zu sein, der Benutzer ich in die zweite Datenbank zu verbinden hat Zugriff nur lesen

Diese für Migrationen gut funktioniert und läuft. Wenn ich jedoch versuche, Tests mit dem Django-Testfall auszuführen, versucht Django, eine Datenbank test_ auf der zweiten Datenbankverbindung zu löschen und zu erstellen.

Wie kann ich sicherstellen, dass Django NIE aktualisieren/löschen/Insert/drop/gestutzt über den zweiten Anschluss

Wie kann ich Tests durchführen, die nicht versuchen, die zweite Datenbank zu schaffen, sondern tun Erstelle das erste.

Danke!

Modell (für die zweite App, die nicht verwaltet werden soll) 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' 

... 

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 

Einstellungen

bearbeitet:

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

ein Testfall:

from django.test.testcases import TestCase 

__author__ = 'CoesseWa' 


class ModelTest(TestCase): 

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

Ausgabe von, wenn diese Tests ausgeführt werden:

... 
Destroying old test user... 

(vor diesem Punkt schafft django die Testdatenbank für meine erste Verbindung = OK)

Creating test user... 

=> Diese nächsten Zeilen sollten niemals vorkommen.Schlägt fehl, weil ich einen Nur-Lese-Benutzer verwenden (zum Glück)

Creating test database for alias 'mdm_db'... 

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

Ich möchte mehr Code sehen, können Sie Ihre Tests und die Modelle zeigen? – Uri

Antwort

10

Ich löste dies durch Ändern der DATABASES.TEST Definition. Ich fügte den TEST['MIRROR'] = 'default' dem mdm_db Datenbankeintrag hinzu.

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

Nach der documentation Diese Option kann die Datenbankerstellung mißbraucht werden überspringen:

jedoch die Replikat-Datenbank als Testspiegel (unter Verwendung der Spiegeltest Einstellung), wurde anzeigt konfiguriert ist, dass Unter Test sollte Replikat als ein Standardspiegel behandelt werden. Wenn die Testumgebung konfiguriert ist, wird keine Testversion des Replikats erstellt. Stattdessen wird die Verbindung zum Replikat umgeleitet, um auf den Standardwert zu verweisen.

Das Ausführen meiner Tests überspringt nun das Erstellen der zweiten Datenbank.

Danke für alle Eingabe !!

+0

danke eine Tonne! das hat sehr geholfen! – TheLuminor

2

Verwenden Sie das --settings Flag mit dem Testbefehl. Im Modul path.to.test.py a la python manage.py test --settings=app.settings.test. Es gibt keine Notwendigkeit, mit Routen herumzualbern, stellen Sie sicher, dass Sie die Tests mit dem Einstellungs-Flag aufrufen, wann immer und wo immer Sie es nennen.

In app.settings.test.py, Ihre DATENBANK Datenstruktur neu zu definieren:

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

Auf diese Weise können Sie eine separate Datenbank verwenden, wenn Tests ausgeführt werden. Wenn Sie sqlite3 als Engine verwenden, werden Sie feststellen, dass Tests sehr schnell ausgeführt werden, wenn sich die Datenbank im Speicher befindet.

Die Verwendung von sqlite3-Datenbanken zum Testen bedeutet, dass sogar Hunderte von Tests innerhalb von Sekunden ausgeführt werden können. Daher können Sie Ihre Tests sehr häufig ausführen. I Karte typischerweise einen Schlüssel, meine Arbeit zu sparen und meine Tests mit einer Aktion ausführen:

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

Hoffnung, das ist hilfreich!

+0

Ich benutze verschiedene Einstellungsdatei ... Das Problem ist, dass ich nicht praktisch über die zweite Datenbank auf meinem lokalen Rechner kopieren kann, um Tests auszuführen. Der Inhalt der seconden-Datenbank ist gewissermaßen Teil der Logik, also muss ich testen, dass meine App damit gut funktioniert. – Ward

+0

Mit den Methoden setUp und tearDown Ihrer Testfälle können Sie Objekte erstellen, gegen die Sie testen können. Ich bin mir nicht sicher, ob das besonders hilfreich ist, aber es könnte etwas wert sein, es anzuschauen. –

Verwandte Themen