使用Pytest在生产环境测试时SQLAlchemy提示未设置SQLALCHEMY_DATABASE_URI的排查方法
问题
我有一个基于Flask的应用,采用SQLAlchemy、应用工厂模式,通过config.py管理配置,同时搭建了自托管GitHub Runner的CI流水线,用Pytest做测试。本地测试全部通过,但在服务器Runner上运行时,SQLAlchemy抛出错误提示未设置SQLALCHEMY_DATABASE_URI,而该配置已经在应用工厂里定义了,该怎么排查?
相关代码文件
extensions.py
from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate # global state for DB connection db = SQLAlchemy() migrate = Migrate()
应用工厂(init.py)
from flask import Flask from app.blueprints.main import main from app.blueprints.api import api from flask_cors import CORS from app.extensions import db, migrate # application factory method used to create the flask app with all the blueprints and extensions def create_app(config=None): #creates the app app = Flask(__name__) # set config if config is None: app.config.from_object('config.BaseConfig') else: app.config.from_object(config) #sets cors to accept everything CORS(app, resources={r"*": {"origins": "*"}}) # init sql alchemy db db.init_app(app) migrate.init_app(app, db) #registers the blueprints app.register_blueprint(main) app.register_blueprint(api) #returns the app return app
config.py
from dotenv import load_dotenv import os load_dotenv() # add app configs here, see __init__.py for how to use them class BaseConfig(object): DEBUG = False TESTING = False SECRET_KEY = os.getenv("SECRET_KEY") SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI") SQLALCHEMY_TRACK_MODIFICATIONS = False class TestingConfig(BaseConfig): TESTING = True
Pytest夹具
@pytest.fixture def app(): app = create_app("config.TestingConfig") return app
错误信息
GitHub Actions控制台输出的错误:
if not engine_options: > raise RuntimeError( "Either 'SQLALCHEMY_DATABASE_URI' or 'SQLALCHEMY_BINDS' must be set." ) E RuntimeError: Either 'SQLALCHEMY_DATABASE_URI' or 'SQLALCHEMY_BINDS' must be set. ../../_tool/Python/3.11.3/x64/lib/python3.11/site-packages/flask_sqlalchemy/extension.py:307: RuntimeError ____________ ERROR at setup of test_FlightData_creates_successfully ____________ @pytest.fixture def app(): > app = create_app("config.TestingConfig")
排查方案
- 验证Runner环境变量加载情况:自托管Runner可能没正确读取到.env变量或系统环境变量。在CI测试步骤前添加命令打印变量(如
echo $SQLALCHEMY_DATABASE_URI),确认变量是否存在。同时检查Runner上代码仓库的根目录是否有.env文件,load_dotenv()默认只加载该路径的文件。 - 给TestingConfig设置独立测试数据库:测试环境不建议依赖外部环境变量,直接在TestingConfig中硬编码内存数据库地址,避免依赖外部配置:
这样既不需要依赖外部环境,也能防止误操作生产数据库。class TestingConfig(BaseConfig): TESTING = True SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:" - 调整环境变量加载时机:
load_dotenv()在config.py导入时执行,如果Runner的环境变量是后续步骤才设置的,会导致加载失败。把load_dotenv()移到应用工厂函数内部,确保创建应用前加载变量:def create_app(config=None): from dotenv import load_dotenv load_dotenv() app = Flask(__name__) # 后续配置代码 - 核对依赖版本一致性:本地和Runner上的Flask-SQLAlchemy版本可能存在差异,新版本的配置检查逻辑更严格。把requirements.txt中的包版本固定,确保两边环境一致。
- 调试应用配置:在Pytest夹具中添加打印配置的代码,查看CI日志确认
SQLALCHEMY_DATABASE_URI是否被正确读取:@pytest.fixture def app(): app = create_app("config.TestingConfig") print("SQLALCHEMY_DATABASE_URI:", app.config.get("SQLALCHEMY_DATABASE_URI")) return app
内容的提问来源于stack exchange,提问作者Graham Billington
相关产品推荐
相关产品推荐

