【问题标题】:Transaction manager revert/rollback last commit事务管理器恢复/回滚上次提交
【发布时间】:2014-09-21 20:21:02
【问题描述】:

我尝试通过将测试用例 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()

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

@classmethod
def tearDownClass(cls):
    session.clear() #delete all
    transaction.commit()

session.close()session.remove() 不会影响已提交的数据。 所以我想办法“取消”setUpClasstransaction.commit(),就像我什么都不种。

我尝试了嵌套事务和保存点,但它们仅在尚未提交数据时才有效。

任何指针?

【问题讨论】:

    标签: python sqlalchemy pyramid


    【解决方案1】:

    如果您不想提交任何事情,请不要致电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()
    

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

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

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

    【讨论】:

    • 我是 ORM 的新手。为什么在应用程序代码中调用 session.commit() 是一种不好的做法?否则你会怎么做? SQLAlchemy 文档似乎建议使用commit(),即使是“大量应用程序”:docs.sqlalchemy.org/en/13/orm/…
    • 啊,我想我知道为什么了。 OP 没有具体说明他正在编写什么样的测试,我猜 Sergey 的建议是针对单元测试的,我 100% 同意。就个人而言,我专注于编写集成测试,这自然会遇到对commit() 的调用,所以我需要一个不同的策略。
    • @mblakesley:我添加了来自 SA 文档的报价。我猜,对于集成测试,您必须采用不同的策略,例如删除/重新创建数据库中的内容
    【解决方案2】:

    setUpClass() 中,您可以创建一个保存点:

    sp = transaction.savepoint()
    

    那么在tearDownClass() 你可以简单地使用:

    sp.rollback()
    

    希望这会有所帮助。

    【讨论】:

    • 你看,sptransaction.commit() 之后会失效,所以如果我尝试做sp.rollback() 它会抛出InvalidSavepointRollbackError: invalidated by a later savepoint,也许transaction.commit() 创建新的保存点,但是接下来如何取回它?在所有种植之前,我需要回滚到预提交状态。
    • 可以声明为类变量stackoverflow.com/questions/68645/…
    • 我知道像 cls.sp 这样的用法,试试这个:sp = transaction.savepoint(); transaction.commit(); sp.rollback()
    猜你喜欢
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 2012-12-24
    相关资源
    最近更新 更多