事务管理器撤销/回滚最后一次提交
我想通过把测试数据放到测试用例的 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()
并不会影响已经提交的数据。所以我在寻找一种方法,像是“取消” setUpClass
的 transaction.commit()
,就好像我什么都没放过一样。
我尝试了嵌套事务和保存点,但这些方法只有在数据还没提交的时候才有效。
有没有什么建议?
2 个回答
1
在 setUpClass()
这个方法里,你可以创建一个保存点,像这样:
sp = transaction.savepoint()
然后在 tearDownClass()
这个方法里,你只需要使用:
sp.rollback()
希望这对你有帮助。
11
如果你不想让某些操作被提交,就不要调用 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)