2015-10-30 8 views
19

Mam aplikacji Django, który wykorzystuje 2 połączeń z bazą danych:Django ignoruje router podczas uruchamiania testów?

  1. Aby połączyć się z rzeczywistymi danymi Aplikacja jest do produkcji
  2. do systemu danych podstawowych odniesienia, która jest utrzymywana całkowicie poza moją kontrolą

Problem, który mam, to to, że moja aplikacja internetowa absolutnie NIE może dotknąć danych w drugiej bazie danych. Rozwiązałem większość problemów za pomocą 2 (pod) aplikacji, po jednej dla każdego połączenia z bazą danych. Stworzyłem plik routera Router żadnej migracji i pisanie do pierwszej aplikacji

Ja również wszystkie modele w 2. aplikacji nie udało, za pomocą opcji

model.meta.managed = False 

.

Aby mieć pewność, użytkownik podłączyć do 2 bazy danych ma dostęp tylko do odczytu

Działa to dobrze dla migracji i działa. Jednak gdy próbuję uruchomić testy przy użyciu testówki django, Django próbuje usunąć i utworzyć bazę danych test_ na drugim połączeniu z bazą danych.

Jak mogę mieć pewność, że Django NIGDY aktualizować/usuwać/insert/drop/obciąć ponad 2. związku

jaki sposób można uruchomić testy, które nie starają się stworzyć druga baza, ale czy stwórz pierwszy.

Dzięki!

edytowany: Kod

modelu (na 2. aplikacji, które nie powinny być zarządzane):

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 

ustawienia:

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

jeden testcase:

from django.test.testcases import TestCase 

__author__ = 'CoesseWa' 


class ModelTest(TestCase): 

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

wyjściowy przy uruchamianiu tego badania:

... 
Destroying old test user... 

(przed tym momencie, Django tworzy bazę testową dla mojego pierwszego połączenia = OK)

Creating test user... 

=> Te następne linie nigdy nie powinny się zdarzyć.Nie powiedzie się, ponieważ używam tylko do odczytu użytkownikowi (na szczęście)

Creating test database for alias 'mdm_db'... 

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

Chciałbym zobaczyć więcej kodu, czy możesz pokazać swoje testy i modele? – Uri

Odpowiedz

10

Rozwiązałem to, zmieniając definicję DATABASES.TEST. Dodałem TEST['MIRROR'] = 'default' do wpisu bazy danych 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 
     } 
    }, 
} 

Według documentation Opcja ta może być nadużywane, aby pominąć tworzenie bazy danych:

Jednak baza Replika została skonfigurowana jako lustro testowym (przy użyciu ustawienia test lustra), wskazując, że podczas testowania replika powinna być traktowana jako zwieranka domyślna.

Po skonfigurowaniu środowiska testowego nie zostanie utworzona wersja testowa repliki . Zamiast tego połączenie z repliką będzie przekierowane do punktu domyślnie.

Przeprowadzanie testów teraz pomija tworzenie drugiej bazy danych.

Dzięki za wszystkie dane wejściowe !!

+0

dzięki za tonę! to bardzo pomogło! – TheLuminor

2

Użyj flagi --settings za pomocą komendy testowej. W module path.to.test.py, a la python manage.py test --settings=app.settings.test. Nie musisz oblewać trasami, po prostu upewnij się, że wywołasz testy z ustawioną flagą zawsze i wszędzie.

W app.settings.test.py, przedefiniować swoją datastructure bazach danych:

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

To pozwala na użycie oddzielnej bazy danych podczas uruchamiania testów. Dodatkowo, jeśli używasz sqlite3 jako swojego silnika, zauważysz, że testy działają bardzo szybko, ponieważ baza danych znajduje się w pamięci.

Używanie baz danych sqlite3 do testowania oznacza, że ​​nawet setki testów można uruchomić w ciągu kilku sekund. W rezultacie bardzo często możesz przeprowadzać testy. Zazwyczaj odwzorowuję klucz, aby zapisać swoją pracę i uruchomić testy jedną czynnością:

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

Mam nadzieję, że to jest pomocne!

+0

Używam różnych plików ustawień ... Problem polega na tym, że nie mogę praktycznie skopiować drugiej bazy danych na mój komputer lokalny, aby uruchomić testy. Treść wtórnej bazy danych jest w pewnym sensie częścią logiki, więc muszę przetestować, czy moja aplikacja działa dobrze z tym. – Ward

+0

Możesz użyć metod setUp i tearDown swoich TestCases do tworzenia obiektów, które możesz przetestować. Nie jestem pewien, czy to jest szczególnie pomocne, ale może warto na to spojrzeć. –