At Enfold Systems, we have been maintaining a staging solution called EnSimpleStaging that has organically grown through the years around customer requirements. My personal opinion is that software that is driven by customer requirements rather than just by plain design based on a good ideas has a higher success rate. But let’s leave that subject to another post.
EnSimpleStaging is based on ZopeVersionControl, another great product which provides for keeping a repository of versioned objects inside the ZODB. One issue we’ve hit constantly with EnSimpleStaging was that certain methods from ZopeVersionControl depend on an actual transaction being commited to properly detect that an object has changed. While in real life this specific method will always work flawlessly due to the way using ZopeVersionControl and EnSimpleStaging works, in a test case it was very hard to test this, due to the fact that a test case is run within a single transaction which is aborted at the end of the test.
Sometime ago I’ve learnt that ZODB has a nifty feature: it is possible to wrap any Storage instance with a DemoStorage. After you do that, you can commit changes and they will be committed to the DemoStorage but not to the base Storage. That would solve not only my problem with ZopeVersionControl, but can potential solve a whole lot set of problems due to expensive setup methods in test cases.
That fact has lived in the back of my mind for longer than two years, until today I set some time aside to investigate a way to implement this cleanly in a way that could be used for my tests. Searching around, I’ve found at least a couple occurrences of other people trying to do the same. I didn’t find any solution though, so that either indicates they just gave up or that they found a solution but didn’t care enough to share it. In fact, the title of this post was borrowed from one of the message subjects, in hope that it will make it easier for other people to find a solution in the future.
My solution (with a test do demonstrate that it works) was based on Jim Fulton’s suggestion to look at zc.selenium. I’ve simply adapted it to the Zope 2 reality, using ZopeTestCase’s provided hooks and `Zope2.bobo_application` (which is the Zope 2 equivalent of the publication object from Zope 3).
Hopefully this will be of use to more people, specially to the folks that were seeking for ideas about how to implement this. It would be even better to just add this to ZopeTestCase proper, I think. Maybe someone will be interested in doing that.
I looked into this whilst working on collective.ploneseltest. From what I can tell, if you derive from FunctionalTestCase, you should get this type of behavior where commits are OK. I don’t entirely remember where FunctionalTestCase does its snapshotting, but it seems to work well in practice.
See http://dev.plone.org/collective/browser/collective.ploneseltest/trunk/collective/ploneseltest/testcase.py for an example.
Ah. You’re right. FunctionalTestCase uses the ‘Sandboxed’ base class, which does pretty much the same as my example does, only it uses 10x more lines to do the same. Yuck!
I implemented nestable sandboxed ZODBs for tightly couple use with zope.testing layers. Check it out and let me know what you think!
http://pypi.python.org/pypi/collective.testcaselayer#collective-testcaselayer-sandbox
Link
https://svn.enfoldsystems.com/browse/public/EnSimpleStaging/trunk/tests/demostorage.py?view=markup “My solution”
shows a 404 not found.
Markus