如何在pytest fixture中清理MySQL数据库?测试退出时程序冻结
解决Flask + TDD测试中
db.drop_all()导致的冻结问题 我之前做Flask TDD开发时也碰到过类似的冻结问题,大概率是数据库会话没正确关闭,或者fixture作用域和数据库操作的生命周期没匹配上。下面给你梳理几个常见的排查方向和解决办法:
1. 先清理会话再执行删表操作
如果SQLAlchemy的会话还持有数据库连接,直接调用db.drop_all()很可能导致数据库锁死,进而让程序卡住。建议在fixture的收尾步骤里先清理会话:
@pytest.fixture(scope="module") def app(): # 你的app初始化、配置代码... yield app # 测试结束后先清理会话,再删表 with app.app_context(): db.session.remove() # 移除当前会话,释放连接 db.drop_all()
2. 统一fixture作用域,避免连接冲突
如果你的数据库fixture是module或session作用域,但测试里还有函数级别的数据库操作,容易出现连接池被占用的情况。可以把涉及数据库的fixture调整为function作用域,确保每个测试后都彻底清理:
@pytest.fixture(scope="function") def db_setup(app): with app.app_context(): db.create_all() yield db.session # 测试结束回滚操作、清理会话、删除表 db.session.rollback() db.session.remove() db.drop_all()
3. 优化数据库引擎配置
试试给Flask-SQLAlchemy加上连接回收的配置,避免闲置连接超时导致的锁死:
app.config["SQLALCHEMY_POOL_RECYCLE"] = 300 # 300秒回收闲置连接 app.config["SQLALCHEMY_POOL_PRE_PING"] = True # 检测连接可用性
4. 强制关闭连接池(终极方案)
如果上面的方法都没效果,可以在删表后手动关闭整个数据库连接池:
with app.app_context(): db.session.remove() db.drop_all() db.engine.dispose() # 强制关闭所有连接,释放资源
你可以先从清理会话的步骤开始试,这是最常见的触发冻结的原因。
内容的提问来源于stack exchange,提问作者Himadri Ganguly
相关产品推荐
相关产品推荐

