2017-10-21 173 views
1

我有一个项目,我定义我的db.py模块:Python的SQLAlchemy的烧瓶模式

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() 

然后我导入db.db到需要查询数据库和插入数据(DB模块。 session.query())。

但是,这意味着当我编写测试代码(pytest)来测试任何导入db.py的模块时,我需要定义“SQLALCHEMY_DATABASE_URI”。一种解决方案是让db是一个懒惰属性,以便上面的代码仅在数据库被使用/测试时才在测试中执行。是否有Flask()+ SQLA + SQLALCHEMY_DATABASE_URI在那里我缺少的常见设计模式?你会如何解决这个问题?烧瓶配置?

回答

1

我们通常解决这个问题的方法是使用application factory和一个配置。

这意味着你在你的项目中,看起来像这样(从文件经修改后服用)有一个函数的地方:

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 

然后(希望你使用pytest)在根目录下的测试,你有一个conftest文件,自动准备测试环境是这样的:

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 

通常情况下,我们创建另一个夹具这也是autouse=True,处理该数据库的建立,冲洗和可能需要加载灯具,并且只能在需要访问数据库的测试中使用该灯具(集成或功能测试),这意味着我们只包含在与我们的集成测试相同的目录中的conftest文件中。