سؤال

I was writing some tests involving ZODB and I got stuck for a long time because of the error I was getting in some unit test. Let's call it Test_B:

Failure/Error: 'NoneType' object has no attribute 'sortKey'
...
 File <<< my code somewhere >>>
     transaction.commit()
 File "/usr/local/lib/python2.7/site-packages/transaction/_manager.py", line 111, in commit
     return self.get().commit()
 File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 280, in commit
     reraise(t, v, tb)
 File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 271, in commit
     self._commitResources()
 File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 386, in _commitResources
     L.sort(key=rm_key)
 File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 555, in rm_key
     return func()
 File "/usr/local/lib/python2.7/site-packages/ZODB/Connection.py", line 813, in sortKey
     return "%s:%s" % (self._storage.sortKey(), id(self))

Thankfully I found out eventually that I forgot to call a transaction.commit() in a test that runs before Test_B called (unsurprisingly) Test_A. The sequence of events as recorded by the log looks thus:

<<< Test_A begins >>>
23:01:41 DEBUG    txn.140735119446400: new transaction
...
<<< no further mentions of txn.140735119446400 being committed or aborted >>>
<<< Test_A ends >>>
<<< Test_B begins >>>
23:01:41 DEBUG    txn.140735119446400: new transaction
23:01:41 DEBUG    my_spec: *** MANUALLY altered DB in Test_B body
...
<<< Test_B bails out due to error >>>

Note that Test A succeeds: this is wrong! I want Test A to fail and tell me I have outstanding changes in a transaction that I had forgotten to commit.

How can I do this with ZODB? I can't find anything in the documentation that I could use to find out whether I'm in a transaction with changes or not.

Obviously, with that check, then I can stick it into the AfterEach block of all my unit tests in the suite.

هل كانت مفيدة؟

المحلول

You'd normally close the connection to the ZODB between tests, to make sure the tests are isolated.

Closing a ZODB connection with an active transaction will raise an exception:

>>> from ZODB.FileStorage import FileStorage
>>> from ZODB.DB import DB
>>> storage = FileStorage('Data.fs')
>>> db = DB(storage)
>>> connection = db.open()
>>> root = connection.root()
>>> root['foo'] = 'bar'
>>> connection.close()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/ZODB/Connection.py", line 286, in close
    raise ConnectionStateError("Cannot close a connection joined to "
ZODB.POSException.ConnectionStateError: Cannot close a connection joined to a transaction
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top