← Back to team overview

launchpad-dev team mailing list archive

create_initialized_view() confusion

 

I have just spent several hours learning this the hard way.

In view tests we often use create_initialized_view() for
convenience. However, there are some things you need to be aware of:

1. The default is to *not* start a new interaction. This means that
   view code that uses get_current_browser_request() - several TAL
   formatters for example - will not find any request.

   Errors related to this problem are sometimes multi-adapter look-up
   errors, where it can be easy to miss that the request is None. Even
   when you do, it can be puzzling as to how that happens. To make it
   worse, the error often comes at the end of an intimidating
   30-level-deep stack trace through the inner workings of ZPT.

2. To get around (1) you can pass current_request=True into
   create_initialized_view(). However, this ends the current
   interaction which has the side-effect of logging out the current
   user. This can be puzzling back in your test case.

3. To get around (1) and (2) you can pass in the current principal to
   create_initialized_view():

     create_initialized_view(
         ...,
         current_request=True,
         principal=get_current_principal())

4. Calling create_initialized_view() with the default arguments for
   current_request (False) and principal (None) can cause confusion:

     >>> login_person(fred)
     >>> view = create_initialized_view(thing, "+someview")
     >>> get_current_principal().person == fred
     True
     >>> view.request.principal == fred
     False
     >>> view.request.principal
     <zope...UnauthenticatedPrincipal ...>

   I think this is actually a bug, but please say so if you disagree.

5. To work around (4) - i.e. when current_request=False - you need to
   call create_initialized_view() with the current principal to ensure
   that the request and interaction principal are the same:

     create_initialized_view(
         ..., principal=get_current_principal())

   It seems that making this create_initialized_view()'s default
   behaviour would make a lot of sense.


Follow ups