[Zope3-checkins] SVN: Zope3/trunk/ - added xmlrpc server proxy for functional testing

Christian Theune ct at gocept.com
Tue Sep 19 06:51:36 EDT 2006


Log message for revision 70225:
   - added xmlrpc server proxy for functional testing
  

Changed:
  U   Zope3/trunk/doc/CHANGES.txt
  U   Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt
  A   Zope3/trunk/src/zope/app/testing/xmlrpc.py

-=-
Modified: Zope3/trunk/doc/CHANGES.txt
===================================================================
--- Zope3/trunk/doc/CHANGES.txt	2006-09-19 10:12:53 UTC (rev 70224)
+++ Zope3/trunk/doc/CHANGES.txt	2006-09-19 10:51:35 UTC (rev 70225)
@@ -10,6 +10,9 @@
 
     New features
 
+      - Added xmlrpclib.ServerProxy variation in zope.app.testing.xmlrpc
+        that allows testing XML-RPC views in functional tests.
+
       - Added attribute `permission` to the `browser:menuItems`-directive to
         allow setting a default value for all menu items defined in this
         directive.
@@ -174,7 +177,8 @@
 
     Much thanks to everyone who contributed to this release:
 
-      Jim Fulton, Dmitry Vasiliev, Martijn Faassen, Christian Theune
+      Jim Fulton, Dmitry Vasiliev, Martijn Faassen, Christian Theune, Wolfgang
+      Schnerring
 
   ------------------------------------------------------------------
 

Modified: Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt	2006-09-19 10:12:53 UTC (rev 70224)
+++ Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt	2006-09-19 10:51:35 UTC (rev 70225)
@@ -60,67 +60,20 @@
 
 And call our xmlrpc method:
 
-  >>> print http(r"""
-  ... POST / HTTP/1.0
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Content-Length: 102
-  ... Content-Type: text/xml
-  ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>contents</methodName>
-  ... <params>
-  ... </params>
-  ... </methodCall>
-  ... """)
-  HTTP/1.0 200 Ok
-  Content-Length: 208
-  Content-Type: text/xml;charset=utf-8
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <params>
-  <param>
-  <value><array><data>
-  <value><string>f1</string></value>
-  <value><string>f2</string></value>
-  </data></array></value>
-  </param>
-  </params>
-  </methodResponse>
-  <BLANKLINE>
+  >>> from zope.app.testing.xmlrpc import ServerProxy
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.contents()
+  ['f1', 'f2']
 
-
 Note that we get an unauthorized error if we don't supply authentication
 credentials:
 
-  >>> print http(r"""
-  ... POST / HTTP/1.0
-  ... Content-Length: 102
-  ... Content-Type: text/xml
-  ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>contents</methodName>
-  ... <params>
-  ... </params>
-  ... </methodCall>
-  ... """)
-  HTTP/1.0 401 Unauthorized
-  Content-Length: 126
-  Content-Type: text/xml;charset=utf-8
-  WWW-Authenticate: basic realm="Zope"
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <params>
-  <param>
-  <value><string></string></value>
-  </param>
-  </params>
-  </methodResponse>
-  <BLANKLINE>
+  >>> proxy = ServerProxy("http://localhost/")
+  >>> proxy.contents()
+  Traceback (most recent call last):
+  ProtocolError: <ProtocolError for localhost/: 401 401 Unauthorized>
 
+
 Named XML-RPC Views
 -------------------
 
@@ -182,64 +135,19 @@
 
 Now, when we access the `contents`, we do so through the listing view:
 
-  >>> print http(r"""
-  ... POST /listing/ HTTP/1.0
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Content-Length: 102
-  ... Content-Type: text/xml
-  ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>contents</methodName>
-  ... <params>
-  ... </params>
-  ... </methodCall>
-  ... """)
-  HTTP/1.0 200 Ok
-  Content-Length: 208
-  Content-Type: text/xml;charset=utf-8
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <params>
-  <param>
-  <value><array><data>
-  <value><string>f1</string></value>
-  <value><string>f2</string></value>
-  </data></array></value>
-  </param>
-  </params>
-  </methodResponse>
-  <BLANKLINE>
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/listing/")
+  >>> proxy.contents()
+  ['f1', 'f2']
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.listing.contents()
+  ['f1', 'f2']
 
 as before, we will get an error if we don't supply credentials:
 
-  >>> print http(r"""
-  ... POST /listing/ HTTP/1.0
-  ... Content-Length: 102
-  ... Content-Type: text/xml
-  ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>contents</methodName>
-  ... <params>
-  ... </params>
-  ... </methodCall>
-  ... """)
-  HTTP/1.0 401 Unauthorized
-  Content-Length: 126
-  Content-Type: text/xml;charset=utf-8
-  WWW-Authenticate: basic realm="Zope"
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <params>
-  <param>
-  <value><string></string></value>
-  </param>
-  </params>
-  </methodResponse>
-  <BLANKLINE>
+  >>> proxy = ServerProxy("http://localhost/listing/")
+  >>> proxy.contents()
+  Traceback (most recent call last):
+  ProtocolError: <ProtocolError for localhost/listing/: 401 401 Unauthorized>
 
 Parameters
 ----------
@@ -278,34 +186,9 @@
 Then we can issue a remote procedure call with a parameter and get
 back, surprise!, the sum:
 
-  >>> print http(r"""
-  ... POST / HTTP/1.0
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Content-Length: 159
-  ... Content-Type: text/xml
-  ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>add</methodName>
-  ... <params>
-  ... <param><int>20</int></param>
-  ... <param><int>22</int></param>
-  ... </params>
-  ... </methodCall>
-  ... """, handle_errors=False)
-  HTTP/1.0 200 Ok
-  Content-Length: 122
-  Content-Type: text/xml;charset=utf-8
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <params>
-  <param>
-  <value><int>42</int></value>
-  </param>
-  </params>
-  </methodResponse>
-  <BLANKLINE>
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.add(20, 22)
+  42
 
 Faults
 ------
@@ -346,40 +229,12 @@
 
 Now, when we call it, we get a proper XML-RPC fault:
 
-  >>> print http(r"""
-  ... POST / HTTP/1.0
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Content-Length: 104
-  ... Content-Type: text/xml
-  ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>your_fault</methodName>
-  ... <params>
-  ... </params>
-  ... </methodCall>
-  ... """, handle_errors=False)
-  HTTP/1.0 200 Ok
-  Content-Length: 272
-  Content-Type: text/xml;charset=utf-8
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <fault>
-  <value><struct>
-  <member>
-  <name>faultCode</name>
-  <value><int>42</int></value>
-  </member>
-  <member>
-  <name>faultString</name>
-  <value><string>It's your fault!</string></value>
-  </member>
-  </struct></value>
-  </fault>
-  </methodResponse>
-  <BLANKLINE>
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.your_fault()
+  Traceback (most recent call last):
+  Fault: <Fault 42: "It's your fault!">
 
+
 DateTime values
 ---------------
 
@@ -420,29 +275,57 @@
 
 Now, when we call it, we get a DateTime value
 
-  >>> print http(r"""
-  ... POST / HTTP/1.0
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Content-Length: 100
-  ... Content-Type: text/xml
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.epoch()
+  <DateTime u'19700101T01:00:01' at ...>
+
+Handling errors with the ServerProxy
+------------------------------------
+
+Our server proxy for functional testing also supports getting the original
+errors from Zope by not handling the errors in the publisher:
+
+
+  >>> class ExceptionDemo:
+  ...     def __init__(self, context, request):
+  ...         self.context = context
+  ...         self.request = request
   ...
-  ... <?xml version='1.0'?>
-  ... <methodCall>
-  ... <methodName>epoch</methodName>
-  ... <params>
-  ... </params>
-  ... </methodCall>
-  ... """, handle_errors=False)
-  HTTP/1.0 200 Ok
-  Content-Length: 163
-  Content-Type: text/xml;charset=utf-8
-  <BLANKLINE>
-  <?xml version='1.0'?>
-  <methodResponse>
-  <params>
-  <param>
-  <value><dateTime.iso8601>19700101T01:00:01</dateTime.iso8601></value>
-  </param>
-  </params>
-  </methodResponse>
-  <BLANKLINE>
+  ...     def your_exception(self):
+  ...         raise Exception("Something went wrong!")
+
+Now we'll register it as a view:
+
+  >>> from zope.configuration import xmlconfig
+  >>> ignored = xmlconfig.string("""
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
+  ...     >
+  ...   <!-- We only need to do this include in this example,
+  ...        Normally the include has already been done for us. -->
+  ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
+  ...
+  ...   <xmlrpc:view
+  ...       for="zope.app.folder.folder.IFolder"
+  ...       methods="your_exception"
+  ...       class="zope.app.publisher.xmlrpc.README.ExceptionDemo"
+  ...       permission="zope.ManageContent"
+  ...       />
+  ... </configure>
+  ... """)
+
+Now, when we call it, we get an XML-RPC fault:
+
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.your_exception()
+  Traceback (most recent call last):
+  Fault: <Fault -1: 'Unexpected Zope exception: Exception: Something went wrong!'>
+
+We can also give the parameter `handleErrors` to have the errors not be
+handled:
+
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/", handleErrors=False)
+  >>> proxy.your_exception()
+  Traceback (most recent call last):
+  Exception: Something went wrong!

Copied: Zope3/trunk/src/zope/app/testing/xmlrpc.py (from rev 70224, Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/testing/xmlrpc.py)



More information about the Zope3-Checkins mailing list