[Zope3-checkins] SVN: Zope3/branches/ctheune-xmlrpc-testing/ Added xmlrpc ServerProxy for functional tests.

Christian Theune ct at gocept.com
Tue Sep 19 04:09:58 EDT 2006


Log message for revision 70220:
   Added xmlrpc ServerProxy for functional tests.
  

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

-=-
Modified: Zope3/branches/ctheune-xmlrpc-testing/doc/CHANGES.txt
===================================================================
--- Zope3/branches/ctheune-xmlrpc-testing/doc/CHANGES.txt	2006-09-19 08:07:35 UTC (rev 70219)
+++ Zope3/branches/ctheune-xmlrpc-testing/doc/CHANGES.txt	2006-09-19 08:09:57 UTC (rev 70220)
@@ -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.

Modified: Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/publisher/xmlrpc/README.txt
===================================================================
--- Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/publisher/xmlrpc/README.txt	2006-09-19 08:07:35 UTC (rev 70219)
+++ Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/publisher/xmlrpc/README.txt	2006-09-19 08:09:57 UTC (rev 70220)
@@ -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,6 @@
 
 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
-  ...
-  ... <?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>
+  >>> proxy = ServerProxy("http://mgr:mgrpw@localhost/")
+  >>> proxy.epoch()
+  <DateTime u'19700101T01:00:01' at ...>

Added: Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/testing/xmlrpc.py
===================================================================
--- Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/testing/xmlrpc.py	2006-09-19 08:07:35 UTC (rev 70219)
+++ Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/testing/xmlrpc.py	2006-09-19 08:09:57 UTC (rev 70220)
@@ -0,0 +1,69 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""XMLRPC testing helpers for Zope 3.
+
+$Id$
+"""
+
+from StringIO import StringIO
+import xmlrpclib 
+
+from zope.app.testing.functional import HTTPCaller
+
+
+REQUEST_TEMPLATE = """POST %(handler)s HTTP/1.0
+Authorization: %(authorization)s
+Content-Length: %(content_length)i
+Content-Type: text/xml
+
+"""
+
+
+class ZopeTestTransport(xmlrpclib.Transport):
+    """xmlrpclib transport that delegates to
+    zope.app.testing.functional.HTTPCaller.
+    """
+
+    verbose = False
+
+    def request(self, host, handler, request_body, verbose=0):
+        request = "POST %s HTTP/1.0\n" % (handler,)
+        request += "Content-Length: %i\n" % len(request_body)
+        request += "Content-Type: text/xml\n"
+
+        host, extra_headers, x509 = self.get_host_info(host)
+        if extra_headers:
+            request += "Authorization: %s\n" % (dict(extra_headers)["Authorization"],)
+
+        request += "\n" + request_body
+        response = HTTPCaller()(request)
+
+        errcode = response.getStatus()
+        errmsg = response.getStatusString()
+        headers = response.getHeaders()
+
+        if errcode != 200:
+            raise xmlrpclib.ProtocolError(
+                host + handler,
+                errcode, errmsg,
+                headers
+                )
+
+        return self._parse_response(StringIO(response.getBody()), sock=None)
+
+
+
+def ServerProxy(uri, transport=ZopeTestTransport(), encoding=None,
+                verbose=0, allow_none=0):
+    return xmlrpclib.ServerProxy(uri, transport, encoding, verbose, allow_none)


Property changes on: Zope3/branches/ctheune-xmlrpc-testing/src/zope/app/testing/xmlrpc.py
___________________________________________________________________
Name: svn:keywords
   + Id Rev Date
Name: svn:eol-style
   + native



More information about the Zope3-Checkins mailing list