2017-10-21 4 views
1

Ich habe ein Projekt und ich habe meine db.py Modul definiert als:Python SQLAlchemy Kolben Muster

app = get_global_flask_app() 
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://foo:[email protected]:5432/test" 
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False 
db = SQLAlchemy(app) 
db.create_all() 

Dann importiere ich db.db in Module, die zum Abfragen der Datenbank benötigen und Daten (db einfügen. session.query()).

Dies bedeutet jedoch, dass wenn ich Testcode (Pytest) schreibe, um jedes Modul zu testen, das db.py importiert, muss ich "SQLALCHEMY_DATABASE_URI" definieren. Eine Lösung besteht darin, dass db ein träge Attribut ist, so dass der obige Code nur dann in Tests ausgeführt wird, wenn die Datenbank verwendet/getestet wird. Gibt es ein gemeinsames Entwurfsmuster für Flask() + SQLA + SQLALCHEMY_DATABASE_URI da draußen, das ich vermisse? Wie würdest du dieses Problem lösen? Flask-Konfig?

Antwort

1

Die Art, wie wir normalerweise dieses Problem lösen, ist mit einem application factory und einer Konfig.

Dies bedeutet, dass Sie eine Funktion irgendwo in Ihrem Projekt haben, das ungefähr so ​​aussieht (aus der Dokumentation mit Änderungen übernommen):

def create_app(config_filename, settings_override=None): 
    app = Flask(__name__) 
    app.config.from_pyfile(config_filename) 
    app.config.from_object(settings_override) 

    from yourapplication.model import db 
    db.init_app(app) 

    from yourapplication.views.admin import admin 
    from yourapplication.views.frontend import frontend 
    app.register_blueprint(admin) 
    app.register_blueprint(frontend) 

    return app 

Dann (und hoffentlich sind Sie mit pytest) in Ihrem Root-Verzeichnis test Sie haben eine conftest Datei, die automatisch die Testumgebung so etwas wie dies bereitet:

import pytest 
from your_project import create_app 


class TestConfig: 
    SQLALCHEMY_DATABASE_URI = "postgresql://foo:[email protected]:5432/test" 
    SQLALCHEMY_TRACK_MODIFICATIONS = False 
    ANY OTHER SETTINGS... 


@pytest.fixture(autouse=True) 
def app(request): 
    app = create_app(settings_override=TestConfig) 
    ctx = app.app_context() 
    ctx.push() 

    def teardown(): 
     ctx.pop() 

    request.addfinalizer(teardown) 

    return app 

Normalerweise erstellen wir eine andere Befestigung, die auch autouse=True ist, dass die DB-Set-up Griffe, bündig und möglicherweise Ladevorrichtungen, und verwenden Sie diese Vorrichtung nur in Tests, die auf die DB (Integration oder Funktionstests) zugreifen müssen, was bedeutet, dass wir einfach in eine conftest Datei in demselben Verzeichnis wie unsere Integrationstests aufnehmen.