SQLAlchemy 2.0下基于PostgreSQL的pytest模块级事务隔离方案失效问题咨询
SQLAlchemy 2.0下基于PostgreSQL的pytest模块级事务隔离方案失效问题咨询
我最近在把一个老代码库从SQLAlchemy 1.3逐步迁移到2.0版本,已经顺利完成了1.3到1.4的过渡,但升级到2.0之后,测试套件里一堆模块出现了「找不到共享测试数据」的问题——奇怪的是没有SQLAlchemy底层报错,和当初从1.3升1.4时的情况完全不一样。
先给大家说下我们用的测试隔离方案:为了避免重复创建测试数据,我们用了两层嵌套事务+monkeypatch替换commit为flush的模式,在1.4下完全正常,但2.0就失效了。具体的fixture代码如下:
from sqlalchemy import Engine from sqlalchemy.orm import Session @pytest.fixture(scope="package") def package_session(test_engine: Engine, monkeypatch_package) -> Session: # 创建包含模块级共享数据的嵌套事务 connection = test_engine.connect() transaction = connection.begin() session = Session(bind=connection) # 把commit替换成flush,这样提交操作只会刷新会话,但不会结束当前事务 monkeypatch_package.setattr(session, "commit", session.flush) # 创建该模块下所有测试共享的基础数据 _create_data_for_test(session) try: yield session finally: transaction.rollback() connection.close() @pytest.fixture(scope="function") def session(package_session): """在外部会话上创建嵌套事务,避免回滚共享数据""" package_session.begin_nested() try: yield package_session finally: package_session.rollback()
简单说下逻辑:
- 模块级的
package_session会创建一个顶层事务,在里面生成共享测试数据,同时把会话的commit方法替换成flush,这样测试里的提交操作不会真正结束事务,共享数据一直存在。 - 每个测试用例用的
sessionfixture会在顶层事务里开一个嵌套事务(对应PostgreSQL的SAVEPOINT),测试结束后回滚这个嵌套事务,这样不会影响模块级的共享数据。
现在升级到2.0后,测试里经常出现找不到共享数据的情况,但没有任何SQLAlchemy的报错提示。我已经折腾了好几天了,实在没头绪——想问问大家,这个模式在SQLAlchemy 2.0里是不是不再支持了?或者我哪里的写法需要适配2.0的新特性?
目前我能想到的替代方案是把共享数据移到函数级fixture里,但这样每个测试都要重复创建数据,测试速度会慢很多,所以还是希望能把原来的模式修好。
内容来源于stack exchange
相关产品推荐
相关产品推荐

