PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Test unitario di Django non riuscito per più schemi Postgres

Gli schemi non vengono utilizzati in molti altri motori DB. Specificando uno schema nei tuoi modelli, hai introdotto una dipendenza nel tuo codice per postgres.

Ci sono due strade che puoi seguire per risolvere il tuo problema;

Innanzitutto, puoi aggiungere un percorso di ricerca predefinito al tuo utente postgres. Lo svantaggio di questo approccio è che gli schemi non possono più essere utilizzati per lo spazio dei nomi, ma il vantaggio è che se il database passa a un motore diverso, il codice funzionerà perfettamente. Lo spazio dei nomi delle tue tabelle può essere ottenuto scegliendo un modo standard di nominare le tue tabelle, simile al modo in cui Django lo fa per impostazione predefinita (ad es. appName_className)

Ci sono due modi per raggiungere questo obiettivo. Il comando postgres per farlo in questo modo è:

ALTER USER (your user) SET search_path = "$user",(schema1),(schema2),(schema3),(...)

Il solo modo django per farlo sarebbe:

# Warning! This is untested, I just glanced at the docs and it looks right.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        # some configuration here
        'OPTIONS': {
            'options': '-c search_path=schema1,schema2,schema3'
        }
    }
}

Vorrai anche cambiare:

db_table = 'cedirData\".\"persons'

a:

db_table = 'persons'

Come bonus, ora puoi utilizzare:

manage.py inspectdb > models.py

che è una bella caratteristica, in questo modo non devi copiare manualmente il tuo database esistente.

Questa soluzione non ti sarà di aiuto, tuttavia, se lo spazio dei nomi dello schema è stato utilizzato in modo massiccio nel database e altre applicazioni si basano su di esso. Un approccio diverso sarebbe quello di scrivere un testrunner personalizzato per creare quegli schemi nel database di test. Questo è un po' più complicato dell'approccio di cui sopra e può essere un po' disordinato. Non ti consiglio di farlo, ma se sei interessato potrei provare ad aiutarti.

Un modo meno disordinato, ma più "hacky" sarebbe semplicemente sovrascrivere il meta durante l'esecuzione dei test. Questo sarebbe anche un testrunner.

from django.test.simple import DjangoTestSuiteRunner
from django.db.models.loading import get_models

class SchemaModelTestRunner(DjangoTestSuiteRunner):
    """Docstring"""
    def setup_test_environment(self, *args, **kwargs):
        self.original_db_tables = {}
        self.schema_models = [m for m in get_models()
                                 if '"."' in m._meta.db_table]
        for m in self.schema_models:
            schema, table = m._meta.db_table.split('"."')
            self.original_db_tables[m] = m._meta.db_table
            m._meta.db_table = 'schema_'+schema+'_table_'+table

        super(SchemaModelTestRunner, self).setup_test_environment(*args,
                                                                   **kwargs)
    def teardown_test_environment(self, *args, **kwargs):
        super(SchemaModelTestRunner, self).teardown_test_environment(*args,
                                                                      **kwargs)
        # reset models
        for m in self.schema_models:
            m._meta.db_table = self.original_db_tables[m]

Dovrai anche definirlo come testrunner nel tuo file settings.py.