Hi Christian, On 21 April 2010 02:58, Christian Theune <c...@gocept.com> wrote: > On 04/20/2010 08:44 PM, Jim Fulton wrote: >> >> On Tue, Apr 20, 2010 at 12:09 PM, Christian Theune<c...@gocept.com> wrote: >>> >>> Minor note: zope.testing *promotes* layers the wrong way and >>> zope.app.testing definitely implements them the wrong way. >> >> That's prety vague. Could you say specifically in what ways >> zope.testing promotes layers the wrong way and > > zope.testing uses the attribute '__bases__' to store the information what > the base layers are. __*__ are supposedly Python internal attributes. > Specifically __bases__ is known to be used to store information which base > classes a class has. > > Looking at this I (and others too) get directed towards: aha, so layers are > classes and use inheritance to signal what base layers are. Which is exactly > not what is happening.
In fact, it's a little worse than that. Consider this pair of layers: class Base: @classmethod def setUp(cls): print "Setting up base" @classmethod def tearDown(cls): print "Tearing down base" class Child(Base): @classmethod def setUp(cls): print "Setting up child" Note that there's no tearDown on the child (perhaps it doesn't need one). What actually happens in this case is that the test runner still finds a tearDown on Child, it's just that it's inherited from Base. So in effect, Base's tearDown is called twice. This also happens with things like testSetUp() and testTearDown(). If the base defines them and a child doesn't, they're called twice. The other problem is that it's hard to also use inheritance in the OOP sense to re-use layer logic. Also, if the layer manages any state, it has to be set as a class variable (on cls), which is effectively global. If you want to re-use a layer but isolate the resources its creates from those created by existing layers, you have to re-implement the layer. These insights by Ross Patterson led to collective.testcaselayer, which was lightly refactored into the layer module of the nascent plone.testing. See: http://svn.plone.org/svn/plone/plone.testing/trunk/src/plone/testing/layer.py http://svn.plone.org/svn/plone/plone.testing/trunk/src/plone/testing/layer.txt http://svn.plone.org/svn/plone/plone.testing/trunk/README.txt This module also contains an implementation of a resource manager that allows layers to define shared resources in a stack that lets child layers shadow those resources (i.e. provide a changed fixture). We use this for things like ZODB connections and Zope 2 app roots. It's explained best in the README, and tested in layer.txt. Having used this pattern for a while, I'm pretty sure it's an improvement on the layers-are-classes thing, which in addition to the problems above, has caused a fair amount of confusion. > > zope.app.testing uses them the wrong way? > > Actually it doesn't. I confused this with Zope 2's Testing: > > There's Testing/ZopeTestCase/layer.py which defines a class with > classmethods and in a similar fashion there is Products.PloneTestCase that > defines classes, derives them and thus kind of piggybacks on the class > inheritance mechanism to establish __bases__ paired with static methods but > without actually inheriting methods. FTR, the ZopeTestCase mess is basically what plone.testing.z2 tries to fix (insofar as it's possible). The PloneTestCase mess will hopefully be fixed by a plone.app.testing building on plone.testing. > We struggled through some hairy details that I fail to remember when we > worked on gocept.selenium last year which tries to establish a generic layer > that can be combined with others. You're not the only one. ;-) Martin _______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org https://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope )