事务管理器恢复/回滚上次提交

Ari*_*hys 8 python sqlalchemy pyramid

我尝试通过将测试数据从测试用例setUp()放到setUpClass()/teardownClass类方法来加速我的测试,因此它不会为测试用例中的每个测试重新创建相同的仅选择夹具.

@classmethod
def setUpClass(cls):
    plant.StuffFactory() #plant stuff with FactoryBoy
    transaction.commit()

@classmethod
def tearDownClass(cls):
    session.query(models.Stuff).delete() # delete planted stuff
    transaction.commit()
Run Code Online (Sandbox Code Playgroud)

但我不喜欢自己删除session.delete的东西,因为我使用了很多模型而不想跟踪我种植的内容.我想要类似的东西

@classmethod
def tearDownClass(cls):
    session.clear() #delete all
    transaction.commit()
Run Code Online (Sandbox Code Playgroud)

但是session.close()session.remove()不会影响提交的数据.所以我寻求某种方式"取消",setUpClass transaction.commit()就像我不种植任何东西.

我尝试嵌套事务和保存点,但它们只有在尚未提交数据的情况下才能工作.

有什么指针吗?

Ser*_*gey 7

如果您不想提交事情,请不要打电话transaction.commit():)

@classmethod
def setUpClass(cls):
    plant.StuffFactory() #plant stuff with FactoryBoy
    # you may possibly want to flush the session, so everything has proper IDs etc.
    DBSession.flush() 
    # let the transaction continue for the duration of the test

@classmethod
def tearDownClass(cls):
    # let the database make everything as if nothing happened
    transaction.rollback()
Run Code Online (Sandbox Code Playgroud)

这将要求您的所有被测代码都没有进行显式事务管理(应用程序代码中的transaction.commit()\ transaction.rollback()),但无论如何这是一个不好的做法:

作为一般规则,应用程序应该在处理特定数据的函数的外部管理会话的生命周期。这是一个基本的关注点分离,它使特定于数据的操作与它们访问和操作该数据的上下文无关。

会话基础知识,SQLAlchemy 文档(https://docs.sqlalchemy.org/en/13/orm/session_basics.html

  • 我是 ORM 新手。为什么在应用程序代码中调用“session.commit()”是一种不好的做法?否则你会怎么做?SQLAlchemy 文档似乎建议即使对于“实质性应用程序”也使用“commit()”:https://docs.sqlalchemy.org/en/13/orm/session_basics.html#when-do-i-construct-a-session -何时提交和何时关闭 (2认同)
  • @mblakesley:我添加了 SA 文档的引用。对于集成测试,我想,您必须有不同的策略,例如删除/重新创建数据库中的内容 (2认同)