Re: [Zope-dev] zope.component test isolation

2011-04-04 Thread Wolfgang Schnerring
Hi,

it seems to me this has stalled somewhat, so I wanted to ask what
people's conclusions are.

* Wolfgang Schnerring w...@gocept.com [2011-03-26 13:41]:
 * Martin Aspeli optilude+li...@gmail.com [2011-03-26 11:22]:
 On 26 March 2011 08:11, Wolfgang Schnerring w...@gocept.com wrote:
 I don't think a fixture of package foo's configuration except
 component X and Y is all that useful.

Whether the the unregister use case is useful remains debatable, but I
personally don't care all *that* much for it, so if the consensus is
that it's overkill I'll go along I guess.

I do care quite a bit for proper getSiteManager() support...

 We do definitely need to allow the global site manager to be stacked
 (which you can achieve with __bases__ as in plone.testing,
 unregistration notwithstanding). But once you do that, the rest is
 pretty easy. The local site manager will always have the global as one
 of its (nested) __bases__.

 I'm sorry, but no, it isn't that easy. When the only local site
 consumer is zope.site, well, maybe. But please think of this in terms
 of zope.component *only*.

 Its API is getSiteManager.sethook(callable), and AFAICT the contract
 is that the return value of callable must provide IComponents
 (briefly: get* and register*). Nowhere does it say that you have to
 delegate back to the global registry, and neither it should. To bring
 up Pyramid once again, they explicitly don't, because they want to
 allow several applications (thus, several registries) coexisting in
 the same process.

 And since we can't assume this delegation, I think there is no other
 way to properly do the stacking than to bend getSiteManager.

... as described here, though. And I wonder if I'm missing something,
because to do that properly looks like quite the can of worms to me.

So, how can we proceed here? Should I (and Thomas) try to get a
proof-of-concept implementation of this based on plone.testing? Or should
we think about what it takes to merge most of plone.testing's ZCA
support into zope.component itself first?

Wolfgang

___
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 )


Re: [Zope-dev] zope.component test isolation

2011-04-04 Thread Martin Aspeli
Hi,

On 4 April 2011 17:30, Wolfgang Schnerring w...@gocept.com wrote:
 So, how can we proceed here? Should I (and Thomas) try to get a
 proof-of-concept implementation of this based on plone.testing? Or should
 we think about what it takes to merge most of plone.testing's ZCA
 support into zope.component itself first?

I think either approach is valuable, and not necessarily mutually exclusive.

I do care about the plone.testing API, which is used in production, so
bear that in mind.

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 )


Re: [Zope-dev] zope.component test isolation

2011-03-26 Thread Wolfgang Schnerring
Hello,

* Martin Aspeli optilude+li...@gmail.com [2011-03-25 13:58]:
 plone.testing (which is Plone non-specific and will shortly be BSD
 licensed) allows for stacking of ZCA registries.
 [...]
 Again, plone.testing is the result of hours and hours of finding weird
 problems, so I'd recommend you don't discard the knowledge there. I
 think a best case scenario would be for plone.testing.zca to just be a
 delegate for something more robust in zope.component.testing.

I wasn't aware plone.testing had something for the ZCA, before I read
that in this thread yesterday. I'm glad to hear that, and I certainly
don't want to discard anything. But from reading the code and what you
wrote, I get the impression that plone.testing does not yet solve the
issue completely, precisely because of the two points I brought up and
that continue below:

 On 25 March 2011 13:17, Jim Fulton j...@zope.com wrote:
  On Fri, Mar 25, 2011 at 4:24 AM, Wolfgang Schnerring w...@gocept.com 
  wrote:
   we realized that just squeezing in a new registry and bending its
   bases to the previously active one is not enough for full isolation,
   since this does not cover *deleting* registrations
 
  Is deleting registrations important?  This seems like an odd use case.
  If it's needed, I would suggest starting with a baseline (e.g. stack)
  that doesn't include the component you want to test deleting, then
  adding in setup.

I've wanted to specifically nuke registrations sometimes, the pattern
being, load the package's configure.zcml in the layer, and then delete
something (to demonstrate some error handling behaviour).

I agree that this use case is rare, but I'm not sure it is rare enough
that we should ignore it. I need to think about this some more,
though.

   2. zope.component has two entry points, the global site registry and
   the current registry (getGlobalSiteManager and getSiteManager).
   The current registry can be anything, or more precisely, you can call
   getSiteManager.sethook(callable) and provide a callable that returns
   the current registry.
  
   I think to provide test support for zope.component (i. e. generally,
   at the library level), we need to support both entry points.
 
  Why? Why would someone care about anything other than the current
  effective configuration.

Because that's the API that zope.component offers, it conceptually
deals with *two* registries: the one you get from getSiteManager and
the one you get from getGlobalSiteManager.

I agree that it is unlikely that client code will *read* registrations
using getGlobalSiteManager -- since most everyone uses
zope.component.getUtility etc. (which in turn uses getSiteManager).
But *writing* is a different matter. Just one example:
zope.component.provideUtility etc. uses getGlobalSiteManager, while
the ZCML directives use getSiteManager.

At least as long as zope.component.provide* uses getGlobalSiteManager
instead of getSiteManager, I maintain that test infrastructure needs to
1. wrap the global registry
2. wrap whatever getSiteManager currently returns
(Otherwise we might be able get away with not doing (1), but I think
we'll always need to do (2).)

plone.testing has it the other way around, doing (1) but not (2), as
Martin says himself...

   The global one is not hard, but the getSiteManager one gets
   nasty really fast, because of course we have to rely on bending
   getSiteManager to return the current test registry
 
 I don't think you need to do that. plone.testing doesn't, for sure, it
 just changes the variable that getSiteManager() looks at.

... and I'm quite sure that's wrong, becasue it doesn't deal with the
issue of getSiteManager at the level of zope.component, but at the
level of some specific implementations (zope.site and
five.localsitemanager, to be precise). When I'm using, say, Pyramid
(which also uses getSiteManager.sethook), this won't help me at all.

And to do this on the level of zope.component, I'm quite sure we are
going to need to override getSiteManager.

   but anyone could at any time call getSiteManager.sethook to
   change it!
  
  Seriously?  Nobody calls that but deep infrastructure code.

 Agree with Jim. Are you going to stop people monkey patching
 getSiteManager() too? ;-)

My point is: Ensuring that test setup always and everywhere happens
precisely so that the code that calls sethook (for example the setup
of zope.site) is called *before* the envisioned test infrastructure
code comes along to bend getSiteManager to do its will seems very
fragile to me, if it's doable at all.

Wolfgang

-- 
Wolfgang Schnerring · w...@gocept.com
gocept gmbh  co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 0 · fax +49 345 1229889 1
Zope and Plone consulting and development
___
Zope-Dev maillist  -  Zope-Dev@zope.org
https://mail.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 

Re: [Zope-dev] zope.component test isolation (was: Zope test layers, pytest, and test isolation)

2011-03-26 Thread Martin Aspeli
Hi Jim,

On 25 March 2011 14:12, Jim Fulton j...@zope.com wrote:

 Agree. There is a problem in that provideAdapter() and friends don't
 use getSiteManager() - the always use the global site manager. And
 there are parts of zope.component that use module level variables
 directly, ignoring hooks.

 These are meant to work this way.

 If you want to do local configuration, you should explictly select the
 relevent registry/manager or call getSiteManager and use the result.

I sortof understand, but it makes it impossible to let people use
provideAdapter()  co in test setup and still retain some kind of
layered test setup, without the kind of hacks we do in plone.testing.

 -- but anyone could at any time
 call getSiteManager.sethook to change it!

 Seriously?  Nobody calls that but deep infrastructure code.

 People do call zope.site.hooks.setHooks() sometimes, though, e.g. upon
 traversal.

 This was never meant to be an application-level feature. I find the
 notion that people would call these dureing traversal to be
 disturbing.  Are you sure you're not confusing this with setSite?

Sorry, I meant setSite() above yes. Although sometimes people call
setHooks() and then setSite(site) in test setup, because setSite()
doesn't work until setHooks() has been called once. I think this may
sometimes just be cargo-cult, though.

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 )


Re: [Zope-dev] zope.component test isolation

2011-03-26 Thread Martin Aspeli
Hi,

On 26 March 2011 08:11, Wolfgang Schnerring w...@gocept.com wrote:
 Hello,

 * Martin Aspeli optilude+li...@gmail.com [2011-03-25 13:58]:
 plone.testing (which is Plone non-specific and will shortly be BSD
 licensed) allows for stacking of ZCA registries.
 [...]
 Again, plone.testing is the result of hours and hours of finding weird
 problems, so I'd recommend you don't discard the knowledge there. I
 think a best case scenario would be for plone.testing.zca to just be a
 delegate for something more robust in zope.component.testing.

 I wasn't aware plone.testing had something for the ZCA, before I read
 that in this thread yesterday. I'm glad to hear that, and I certainly
 don't want to discard anything. But from reading the code and what you
 wrote, I get the impression that plone.testing does not yet solve the
 issue completely, precisely because of the two points I brought up and
 that continue below:

It certainly doesn't solve the unregister (non-?)use case. It has
the advantage of being in use in the wild today, though. :-)

 On 25 March 2011 13:17, Jim Fulton j...@zope.com wrote:
  On Fri, Mar 25, 2011 at 4:24 AM, Wolfgang Schnerring w...@gocept.com 
  wrote:
   we realized that just squeezing in a new registry and bending its
   bases to the previously active one is not enough for full isolation,
   since this does not cover *deleting* registrations
 
  Is deleting registrations important?  This seems like an odd use case.
  If it's needed, I would suggest starting with a baseline (e.g. stack)
  that doesn't include the component you want to test deleting, then
  adding in setup.

 I've wanted to specifically nuke registrations sometimes, the pattern
 being, load the package's configure.zcml in the layer, and then delete
 something (to demonstrate some error handling behaviour).

 I agree that this use case is rare, but I'm not sure it is rare enough
 that we should ignore it. I need to think about this some more,
 though.

It would be better to explicitly register what you need.

I think you either need to consider a package's ZCML-loaded
configuration as an atomic part of test setup, or you need to break it
down into individual registrations. In the first case, your test
fixture is package foo's configuration is loaded, which is of course
valid. In the second case, your fixture is the following components,
some of which happen to be in package foo, are registered.

I don't think a fixture of package foo's configuration except
component X and Y is all that useful.

Of course, there may be cases where an unregister is needed, but this
is probably something you should solve locally. For example, you can
explicitly unregister the component at the beginning of your test and
reinstate it at the end of your test, or indeed in layer setup and
tear-down. Automating this with stacking is not a great win.

Please also take my word for it when I say that copying the whole
registry is non-trivial and would rely on brittle ZCA internals. I
tried. :)

   2. zope.component has two entry points, the global site registry and
   the current registry (getGlobalSiteManager and getSiteManager).
   The current registry can be anything, or more precisely, you can call
   getSiteManager.sethook(callable) and provide a callable that returns
   the current registry.
  
   I think to provide test support for zope.component (i. e. generally,
   at the library level), we need to support both entry points.
 
  Why? Why would someone care about anything other than the current
  effective configuration.

 Because that's the API that zope.component offers, it conceptually
 deals with *two* registries: the one you get from getSiteManager and
 the one you get from getGlobalSiteManager.

 I agree that it is unlikely that client code will *read* registrations
 using getGlobalSiteManager -- since most everyone uses
 zope.component.getUtility etc. (which in turn uses getSiteManager).
 But *writing* is a different matter. Just one example:
 zope.component.provideUtility etc. uses getGlobalSiteManager, while
 the ZCML directives use getSiteManager.

 At least as long as zope.component.provide* uses getGlobalSiteManager
 instead of getSiteManager, I maintain that test infrastructure needs to
 1. wrap the global registry
 2. wrap whatever getSiteManager currently returns
 (Otherwise we might be able get away with not doing (1), but I think
 we'll always need to do (2).)

 plone.testing has it the other way around, doing (1) but not (2), as
 Martin says himself...

We do definitely need to allow the global site manager to be stacked
(which you can achieve with __bases__ as in plone.testing,
unregistration notwithstanding). But once you do that, the rest is
pretty easy. The local site manager will always have the global as one
of its (nested) __bases__.

My preference would be:

 - We replace the three separate module-level references to the global
site manager with a single object
 - This object is a holder for a registry reference 

Re: [Zope-dev] zope.component test isolation

2011-03-26 Thread Wolfgang Schnerring
Hello,

* Martin Aspeli optilude+li...@gmail.com [2011-03-26 11:22]:
 On 26 March 2011 08:11, Wolfgang Schnerring w...@gocept.com wrote:
  * Martin Aspeli optilude+li...@gmail.com [2011-03-25 13:58]:
 Please also take my word for it when I say that copying the whole
 registry is non-trivial and would rely on brittle ZCA internals. I
 tried. :)

I tried, too, and yup, in the end you'd have to write C to do it
properly (because the AdapterLookupBase or something in zope.interface
is written in C and would need to gain __deepcopy__ support).
But it didn't seem unfeasible, and, when it was all said and done in
Python, not very ugly either.

I appreciate that you've already fought (and won!) against the
whole persistence story (which hadn't even been on my radar so far),
and I guess copying would necessitate reopening that can of worms.

  I've wanted to specifically nuke registrations sometimes, the pattern
  being, load the package's configure.zcml in the layer, and then delete
  something (to demonstrate some error handling behaviour).
 
 I think you either need to consider a package's ZCML-loaded
 configuration as an atomic part of test setup, or you need to break it
 down into individual registrations. In the first case, your test
 fixture is package foo's configuration is loaded, which is of course
 valid. In the second case, your fixture is the following components,
 some of which happen to be in package foo, are registered.
 
 I don't think a fixture of package foo's configuration except
 component X and Y is all that useful.

It seems I can't convey why I think that precisely this is valuable
even without taking into account the desire for non-leaky
abstractions (in the ZODB-analogy it would be quite strange to have to
write on top, please don't delete stuff, it's not supported).

And of course I know how one could work around the limitation that
unregistering is not supported. That doesn't make it any less
inconvenient.

The other point about getSiteManager below is *much* more important
than unregistration support, though:

  Because that's the API that zope.component offers, it conceptually
  deals with *two* registries: the one you get from getSiteManager and
  the one you get from getGlobalSiteManager.
 
  I agree that it is unlikely that client code will *read* registrations
  using getGlobalSiteManager -- since most everyone uses
  zope.component.getUtility etc. (which in turn uses getSiteManager).
  But *writing* is a different matter. Just one example:
  zope.component.provideUtility etc. uses getGlobalSiteManager, while
  the ZCML directives use getSiteManager.
 
  At least as long as zope.component.provide* uses getGlobalSiteManager
  instead of getSiteManager, I maintain that test infrastructure needs to
  1. wrap the global registry
  2. wrap whatever getSiteManager currently returns
  (Otherwise we might be able get away with not doing (1), but I think
  we'll always need to do (2).)
 
  plone.testing has it the other way around, doing (1) but not (2), as
  Martin says himself...

 We do definitely need to allow the global site manager to be stacked
 (which you can achieve with __bases__ as in plone.testing,
 unregistration notwithstanding). But once you do that, the rest is
 pretty easy. The local site manager will always have the global as one
 of its (nested) __bases__.

I'm sorry, but no, it isn't that easy. When the only local site
consumer is zope.site, well, maybe. But please think of this in terms
of zope.component *only*.

Its API is getSiteManager.sethook(callable), and AFAICT the contract
is that the return value of callable must provide IComponents
(briefly: get* and register*). Nowhere does it say that you have to
delegate back to the global registry, and neither it should. To bring
up Pyramid once again, they explicitly don't, because they want to
allow several applications (thus, several registries) coexisting in
the same process.

And since we can't assume this delegation, I think there is no other
way to properly do the stacking than to bend getSiteManager.

Wolfgang

-- 
Wolfgang Schnerring · w...@gocept.com
gocept gmbh  co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 0 · fax +49 345 1229889 1
Zope and Plone consulting and development
___
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 )


Re: [Zope-dev] zope.component test isolation (was: Zope test layers, pytest, and test isolation)

2011-03-25 Thread Wolfgang Schnerring
Hello Uli,

I've spent quite some time thinking (and partly coding) about the same
issues you mention (but didn't feel ready to talk about it here, yet),
so I'm glad that maybe we can start thinking about them together

I think your email addresses two quite different topics, so I'll split
my reply. First up: test support for zope.component. Second part:
about the concept of test layers.

* Uli Fouquet u...@gnufix.de [2011-03-24 01:05]:
 Right now we have a problem with pytest integration when it comes to
 ZCA setups [...] all tests share the same global ZCA registrations
 and changes to the registrations in one test will affect other tests
 run thereafter. We have a lack of test isolation.

Exactly. This issue has bitten me too in various places, and as far as
I know there are no solutions for it, yet.

What I envision to solve this issue is that test support for
zope.component should work the same way as with the ZODB. There, we
have a *stack* of Databases (DemoStorages, to be precise) that wrap
each other, where each one delegates reads downwards, but keeps writes
for itself. So you might have one database for the layer that provides
the baseline, and each test (in its setUp) gets its own database where
it can do whatever it wants, because it is thrown away in its
tearDown.

In principle, quite a few of the mechanics to do the same thing with
zope.component registries are already there (since a registry keeps a
list of base registries it will delegate to when something can not be
found in itself). And as Hanno and Godefroid mentioned, plone.testing
does something in this direction already. (And, it bears repeating,
in its core has no dependencies on Plone or Zope2.)

But as far as I see, there are issues that plone.testing does not
address:

1. I've been going over this stuff with my colleague Thomas Lotze, and
we realized that just squeezing in a new registry and bending its
bases to the previously active one is not enough for full isolation,
since this does not cover *deleting* registrations (one, you can only
delete the registration from the precise registry it was created in,
and two, in the just-bend-the-bases approach, once you delete a
registration, it's gone forever).

I think to provide full isolation, we need to make *copies*. And since
zope.component in general supports a chain of registries, we probably
need to make copies of each of them.

2. zope.component has two entry points, the global site registry and
the current registry (getGlobalSiteManager and getSiteManager).
The current registry can be anything, or more precisely, you can call
getSiteManager.sethook(callable) and provide a callable that returns
the current registry.

I think to provide test support for zope.component (i. e. generally,
at the library level), we need to support both entry points. The
global one is not hard, but the getSiteManager one gets nasty really
fast, because of course we have to rely on bending getSiteManager to
return the current test registry -- but anyone could at any time
call getSiteManager.sethook to change it! Which means we need to
intercept that and a) prevent our hook from being replaced and b)
inject the new registry into the test stack somehow.

As far as I understand, plone.testing sidesteps these issues by only
dealing with the global registry, and specially munging the two known
cases in the Zope world where getSiteManager is changed (zope.site and
five.something).

**

I'd like to know what people think about this plan.
Thomas and I have been over this quite a bit and think it's sound, not
overly complicated, and (after we did some experiments) definitely
doable. Please do point out stuff we missed. :-)

I'd very much like to put this functionality into zope.component
itself, which of course raises backwards compatibility issues galore,
but any code for this definitely isn't wasted since we can always
package it separately if we don't find a way to integrate it.

Thomas and I taken up implementing this, but we can't devote a lot of
time to it (about one session per week), so realistically I'm afraid I
guess it will take a few months until we have something of substance.
So if there are people who want to pitch in, that'd be great. I
definitely could write up a more detailed plan and maybe even
formulate smaller chunks so we could go at this with more people.

Wolfgang

-- 
Wolfgang Schnerring · w...@gocept.com
gocept gmbh  co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 0 · fax +49 345 1229889 1
Zope and Plone consulting and development
___
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 )


Re: [Zope-dev] zope.component test isolation (was: Zope test layers, pytest, and test isolation)

2011-03-25 Thread Jim Fulton
On Fri, Mar 25, 2011 at 4:24 AM, Wolfgang Schnerring w...@gocept.com wrote:
 Hello Uli,

 I've spent quite some time thinking (and partly coding) about the same
 issues you mention (but didn't feel ready to talk about it here, yet),
 so I'm glad that maybe we can start thinking about them together

 I think your email addresses two quite different topics, so I'll split
 my reply. First up: test support for zope.component. Second part:
 about the concept of test layers.

 * Uli Fouquet u...@gnufix.de [2011-03-24 01:05]:
 Right now we have a problem with pytest integration when it comes to
 ZCA setups [...] all tests share the same global ZCA registrations
 and changes to the registrations in one test will affect other tests
 run thereafter. We have a lack of test isolation.

 Exactly. This issue has bitten me too in various places, and as far as
 I know there are no solutions for it, yet.

The classic solution is to start tests with empty registries, or, if
you're using layers, with some baseline registries.

 What I envision to solve this issue is that test support for
 zope.component should work the same way as with the ZODB. There, we
 have a *stack* of Databases (DemoStorages, to be precise) that wrap
 each other, where each one delegates reads downwards, but keeps writes
 for itself. So you might have one database for the layer that provides
 the baseline, and each test (in its setUp) gets its own database where
 it can do whatever it wants, because it is thrown away in its
 tearDown.

 In principle, quite a few of the mechanics to do the same thing with
 zope.component registries are already there (since a registry keeps a
 list of base registries it will delegate to when something can not be
 found in itself). And as Hanno and Godefroid mentioned, plone.testing
 does something in this direction already. (And, it bears repeating,
 in its core has no dependencies on Plone or Zope2.)

I like the idea of stacking registries.

 But as far as I see, there are issues that plone.testing does not
 address:

 1. I've been going over this stuff with my colleague Thomas Lotze, and
 we realized that just squeezing in a new registry and bending its
 bases to the previously active one is not enough for full isolation,
 since this does not cover *deleting* registrations (one, you can only
 delete the registration from the precise registry it was created in,
 and two, in the just-bend-the-bases approach, once you delete a
 registration, it's gone forever).

 I think to provide full isolation, we need to make *copies*. And since
 zope.component in general supports a chain of registries, we probably
 need to make copies of each of them.

Is deleting registrations important?  This seems like an odd use case.
If it's needed, I would suggest starting with a baseline (e.g. stack)
that doesn't include the component you want to test deleting, then
adding in setup.


 2. zope.component has two entry points, the global site registry and
 the current registry (getGlobalSiteManager and getSiteManager).
 The current registry can be anything, or more precisely, you can call
 getSiteManager.sethook(callable) and provide a callable that returns
 the current registry.

 I think to provide test support for zope.component (i. e. generally,
 at the library level), we need to support both entry points.

Why?  Why would someone care about anything other than the current
effective configuration.

 The
 global one is not hard, but the getSiteManager one gets nasty really
 fast, because of course we have to rely on bending getSiteManager to
 return the current test registry

But as you point out, there's a hook for that.

 -- but anyone could at any time
 call getSiteManager.sethook to change it!

Seriously?  Nobody calls that but deep infrastructure code.

 Which means we need to
 intercept that and a) prevent our hook from being replaced and b)
 inject the new registry into the test stack somehow.

I think you're making this more complicated than it needs to be.

 As far as I understand, plone.testing sidesteps these issues by only
 dealing with the global registry, and specially munging the two known
 cases in the Zope world where getSiteManager is changed (zope.site and
 five.something).

 **

 I'd like to know what people think about this plan.
 Thomas and I have been over this quite a bit and think it's sound, not
 overly complicated, and (after we did some experiments) definitely
 doable. Please do point out stuff we missed. :-)

I think a stack-based approach is very appealing.  I think anything
more complex is likely to cause more problems than it solves.

 I'd very much like to put this functionality into zope.component
 itself, which of course raises backwards compatibility issues
 galore,

Not sure why this would have to be backward incompatible, but I'm
unconvinced that the complexity comes close to being justified by the
benefit.


 but any code for this definitely isn't wasted since we can always
 package it separately if we 

Re: [Zope-dev] zope.component test isolation (was: Zope test layers, pytest, and test isolation)

2011-03-25 Thread Martin Aspeli
Hi,

On 25 March 2011 13:17, Jim Fulton j...@zope.com wrote:
 On Fri, Mar 25, 2011 at 4:24 AM, Wolfgang Schnerring w...@gocept.com wrote:
 Hello Uli,

 I've spent quite some time thinking (and partly coding) about the same
 issues you mention (but didn't feel ready to talk about it here, yet),
 so I'm glad that maybe we can start thinking about them together

 I think your email addresses two quite different topics, so I'll split
 my reply. First up: test support for zope.component. Second part:
 about the concept of test layers.

 * Uli Fouquet u...@gnufix.de [2011-03-24 01:05]:
 Right now we have a problem with pytest integration when it comes to
 ZCA setups [...] all tests share the same global ZCA registrations
 and changes to the registrations in one test will affect other tests
 run thereafter. We have a lack of test isolation.

 Exactly. This issue has bitten me too in various places, and as far as
 I know there are no solutions for it, yet.

 The classic solution is to start tests with empty registries, or, if
 you're using layers, with some baseline registries.

plone.testing (which is Plone non-specific and will shortly be BSD
licensed) allows for stacking of ZCA registries. It has to do some
ugly hacking to achieve this, since zope.component stores handles to
the global registry in *three* different modules and update them in
weird ways depending on the registry hooking, but it's well tested and
robust now.

See 
http://dev.plone.org/plone/browser/plone.testing/trunk/src/plone/testing/zca.py
and 
http://dev.plone.org/plone/browser/plone.testing/trunk/src/plone/testing/zca.txt.

 What I envision to solve this issue is that test support for
 zope.component should work the same way as with the ZODB. There, we
 have a *stack* of Databases (DemoStorages, to be precise) that wrap
 each other, where each one delegates reads downwards, but keeps writes
 for itself. So you might have one database for the layer that provides
 the baseline, and each test (in its setUp) gets its own database where
 it can do whatever it wants, because it is thrown away in its
 tearDown.

 In principle, quite a few of the mechanics to do the same thing with
 zope.component registries are already there (since a registry keeps a
 list of base registries it will delegate to when something can not be
 found in itself). And as Hanno and Godefroid mentioned, plone.testing
 does something in this direction already. (And, it bears repeating,
 in its core has no dependencies on Plone or Zope2.)

 I like the idea of stacking registries.

plone.testing implements this.

If we could fix zope.component to make the implementation less ugly,
that'd be a big win.

 But as far as I see, there are issues that plone.testing does not
 address:

 1. I've been going over this stuff with my colleague Thomas Lotze, and
 we realized that just squeezing in a new registry and bending its
 bases to the previously active one is not enough for full isolation,
 since this does not cover *deleting* registrations (one, you can only
 delete the registration from the precise registry it was created in,
 and two, in the just-bend-the-bases approach, once you delete a
 registration, it's gone forever).

Correct, although this is in practice extremely rare. I'd say it's
much better to control setup more carefully and not have to undo in
a child layer.

 I think to provide full isolation, we need to make *copies*. And since
 zope.component in general supports a chain of registries, we probably
 need to make copies of each of them.

Copying is very hard. It was my first attempt in plone.testing and
didn't work out well. You need to support pickling of registries for
local/persistent component registries. I cannot begin to tell you how
many weird pickling errors I found and had to work around.

 Is deleting registrations important?  This seems like an odd use case.
 If it's needed, I would suggest starting with a baseline (e.g. stack)
 that doesn't include the component you want to test deleting, then
 adding in setup.

+1

 2. zope.component has two entry points, the global site registry and
 the current registry (getGlobalSiteManager and getSiteManager).
 The current registry can be anything, or more precisely, you can call
 getSiteManager.sethook(callable) and provide a callable that returns
 the current registry.

 I think to provide test support for zope.component (i. e. generally,
 at the library level), we need to support both entry points.

 Why?  Why would someone care about anything other than the current
 effective configuration.

Agree. There is a problem in that provideAdapter() and friends don't
use getSiteManager() - the always use the global site manager. And
there are parts of zope.component that use module level variables
directly, ignoring hooks.

 The
 global one is not hard, but the getSiteManager one gets nasty really
 fast, because of course we have to rely on bending getSiteManager to
 return the current test registry

 But as you point 

Re: [Zope-dev] zope.component test isolation (was: Zope test layers, pytest, and test isolation)

2011-03-25 Thread Jim Fulton
On Fri, Mar 25, 2011 at 9:58 AM, Martin Aspeli optilude+li...@gmail.com wrote:
 On 25 March 2011 13:17, Jim Fulton j...@zope.com wrote:
 On Fri, Mar 25, 2011 at 4:24 AM, Wolfgang Schnerring w...@gocept.com wrote:

...

 2. zope.component has two entry points, the global site registry and
 the current registry (getGlobalSiteManager and getSiteManager).
 The current registry can be anything, or more precisely, you can call
 getSiteManager.sethook(callable) and provide a callable that returns
 the current registry.

 I think to provide test support for zope.component (i. e. generally,
 at the library level), we need to support both entry points.

 Why?  Why would someone care about anything other than the current
 effective configuration.

 Agree. There is a problem in that provideAdapter() and friends don't
 use getSiteManager() - the always use the global site manager. And
 there are parts of zope.component that use module level variables
 directly, ignoring hooks.

These are meant to work this way.

If you want to do local configuration, you should explictly select the
relevent registry/manager or call getSiteManager and use the result.

 -- but anyone could at any time
 call getSiteManager.sethook to change it!

 Seriously?  Nobody calls that but deep infrastructure code.

 People do call zope.site.hooks.setHooks() sometimes, though, e.g. upon
 traversal.

This was never meant to be an application-level feature. I find the
notion that people would call these dureing traversal to be
disturbing.  Are you sure you're not confusing this with setSite?

Jim

--
Jim Fulton
http://www.linkedin.com/in/jimfulton
___
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 )


Re: [Zope-dev] zope.component test isolation

2011-03-25 Thread Tres Seaver
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 03/25/2011 09:58 AM, Martin Aspeli wrote:

 I would suggest a good starting point would be to see if you can make
 plone.testing.zca clean. It should be pretty obvious what is
 currently a hack. If you got there, you effectively have stacking of
 component registries. plone.testing would be simpler, and
 zope.component.testing would be able to provide a simple way to stack
 configuration by layer without a plone.testing dependency.
 
 If you ignore the delete use case (which I think is a non-use case),
 I think this is quite achievable in a sprint, say.

+1 to this approach.


Tres.
- -- 
===
Tres Seaver  +1 540-429-0999  tsea...@palladion.com
Palladion Software   Excellence by Designhttp://palladion.com
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk2MpBsACgkQ+gerLs4ltQ7QQACgycVfipd/FvF6J8swGRJpZ2M9
SzcAniu9uvBS58WDcgxTxxllY+q8UmNX
=Ljpu
-END PGP SIGNATURE-

___
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 )