I try to speedup my tests by putting test data from test case setUp()
to setUpClass()/teardownClass
class method, so it does not recreate same select only fixture for every test in test case.
@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()
But i don't like deleting stuff with session.delete on my own, because i use many models and don't want track what i planted. I want something like
@classmethod
def tearDownClass(cls):
session.clear() #delete all
transaction.commit()
But session.close()
or session.remove()
will not affect committed data.
So i seek some way to "cancel" setUpClass
transaction.commit()
like i don't plant anything.
I try nested transactions and savepoints but again they works only if data not committed yet.
Any pointers?
COMMIT permanently saves the changes made by the current transaction. ROLLBACK undo the changes made by the current transaction. 2. The transaction can not undo changes after COMMIT execution.
Once SQL Server commits a transaction, you cannot run the ROLLBACK statement.
A COMMIT statement is used to save the changes on the current transaction is permanent. A Rollback statement is used to undo all the changes made on the current transaction. Once the current transaction is completely executed using the COMMIT command, it can't undo its previous state.
I have confirmed that after rollback we cannot commit the same transaction. Make sure another transaction is not in waiting, else it will be committed. Also don't do anything with transaction in finally block. Always use finally block to close connection , data reader etc.
If you don't want things to be committed, simply don't call 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()
This would require that none of your code under test does explicit transaction management (transaction.commit()
\ transaction.rollback()
in application code), but that's a bad practice anyway:
As a general rule, the application should manage the lifecycle of the session externally to functions that deal with specific data. This is a fundamental separation of concerns which keeps data-specific operations agnostic of the context in which they access and manipulate that data.
Session Basics, SQLAlchemy Documentation (https://docs.sqlalchemy.org/en/13/orm/session_basics.html)
In setUpClass()
you could create a save point as:
sp = transaction.savepoint()
then in tearDownClass()
you could simply use:
sp.rollback()
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With