Question

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.

Était-ce utile?

La solution

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top