[Checkins] SVN: zope.testbrowser/tags/3.10.3/ Added `wsgi_intercept` support (came from ``zope.app.wsgi.testlayer``).
Michael Howitz
mh at gocept.com
Mon Jan 24 09:03:18 EST 2011
Log message for revision 119872:
Added `wsgi_intercept` support (came from ``zope.app.wsgi.testlayer``).
Changed:
U zope.testbrowser/tags/3.10.3/CHANGES.txt
U zope.testbrowser/tags/3.10.3/setup.py
U zope.testbrowser/tags/3.10.3/src/zope/testbrowser/README.txt
A zope.testbrowser/tags/3.10.3/src/zope/testbrowser/tests/test_wsgi.py
A zope.testbrowser/tags/3.10.3/src/zope/testbrowser/wsgi.py
-=-
Modified: zope.testbrowser/tags/3.10.3/CHANGES.txt
===================================================================
--- zope.testbrowser/tags/3.10.3/CHANGES.txt 2011-01-24 13:35:14 UTC (rev 119871)
+++ zope.testbrowser/tags/3.10.3/CHANGES.txt 2011-01-24 14:03:18 UTC (rev 119872)
@@ -2,16 +2,22 @@
CHANGES
=======
+3.11.0 (unreleased)
+-------------------
+
+- Added `wsgi_intercept` support (came from ``zope.app.wsgi.testlayer``).
+
+
3.10.3 (2010-10-15)
-------------------
-- Fixed backwards compatibility with zope.app.wsgi.testlayer.
+- Fixed backwards compatibility with ``zope.app.wsgi.testlayer``.
3.10.2 (2010-10-15)
-------------------
-- Fixed Python2.7 compatibility in Browser.handleErrors.
+- Fixed Python 2.7 compatibility in Browser.handleErrors.
3.10.1 (2010-09-21)
Modified: zope.testbrowser/tags/3.10.3/setup.py
===================================================================
--- zope.testbrowser/tags/3.10.3/setup.py 2011-01-24 13:35:14 UTC (rev 119871)
+++ zope.testbrowser/tags/3.10.3/setup.py 2011-01-24 14:03:18 UTC (rev 119872)
@@ -74,6 +74,9 @@
'zope-functional-testing': [
'zope.app.testing',
],
+ 'wsgi': [
+ 'wsgi_intercept',
+ ]
},
include_package_data = True,
zip_safe = False,
Modified: zope.testbrowser/tags/3.10.3/src/zope/testbrowser/README.txt
===================================================================
--- zope.testbrowser/tags/3.10.3/src/zope/testbrowser/README.txt 2011-01-24 13:35:14 UTC (rev 119871)
+++ zope.testbrowser/tags/3.10.3/src/zope/testbrowser/README.txt 2011-01-24 14:03:18 UTC (rev 119872)
@@ -2,6 +2,12 @@
Detailed Documentation
======================
+Different Browsers
+------------------
+
+HTTP Browser
+~~~~~~~~~~~~
+
The ``zope.testbrowser.browser`` module exposes a ``Browser`` class that
simulates a web browser similar to Mozilla Firefox or IE.
@@ -11,6 +17,38 @@
This version of the browser object can be used to access any web site just as
you would do using a normal web browser.
+WSGI Test Browser
+~~~~~~~~~~~~~~~~~
+
+There is also a special version of the ``Browser`` class which uses
+`wsgi_intercept`_ and can be used to do functional testing of WSGI
+applications, it can be imported from ``zope.testbrowser.wsgi``:
+
+ >>> from zope.testbrowser.wsgi import Browser
+ >>> browser = Browser()
+
+.. _`wsgi_intercept`: http://pypi.python.org/pypi/wsgi_intercept
+
+To use this browser you have to:
+
+ * use the `wsgi` extra of the ``zope.testbrowser`` egg,
+
+ * write a subclass of ``zope.testbrowser.wsgi.Layer`` and override the
+ ``make_wsgi_app`` method,
+
+ * use an instance of the class as the test layer of your test.
+
+Example:
+
+ >>> class SimpleLayer(zope.testbrowser.wsgi.Layer):
+ ... def make_wsgi_app(self):
+ ... return simple_app
+
+Where ``simple_app`` is the callable of your WSGI application.
+
+Zope 3 Test Browser
+~~~~~~~~~~~~~~~~~~~
+
There is also a special version of the ``Browser`` class used to do functional
testing of Zope 3 applications, it can be imported from
``zope.testbrowser.testing``:
@@ -18,8 +56,12 @@
>>> from zope.testbrowser.testing import Browser
>>> browser = Browser()
-An initial page to load can be passed to the ``Browser`` constructor:
+Bowser Usage
+------------
+All browsers are used the same way. An initial page to load can be passed
+to the ``Browser`` constructor:
+
>>> browser = Browser('http://localhost/@@/testbrowser/simple.html')
>>> browser.url
'http://localhost/@@/testbrowser/simple.html'
Added: zope.testbrowser/tags/3.10.3/src/zope/testbrowser/tests/test_wsgi.py
===================================================================
--- zope.testbrowser/tags/3.10.3/src/zope/testbrowser/tests/test_wsgi.py (rev 0)
+++ zope.testbrowser/tags/3.10.3/src/zope/testbrowser/tests/test_wsgi.py 2011-01-24 14:03:18 UTC (rev 119872)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2011 Zope Foundation 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.
+#
+##############################################################################
+
+import unittest
+import zope.testbrowser.wsgi
+
+
+# Copied from PEP #333
+def simple_app(environ, start_response):
+ """Simplest possible application object"""
+ status = '200 OK'
+ response_headers = [('Content-type', 'text/plain')]
+ start_response(status, response_headers)
+ return ['Hello world!\n']
+
+
+class SimpleLayer(zope.testbrowser.wsgi.Layer):
+
+ def make_wsgi_app(self):
+ return simple_app
+
+SIMPLE_LAYER = SimpleLayer()
+
+
+class TestWSGI(unittest.TestCase):
+
+ layer = SIMPLE_LAYER
+
+ def test_(self):
+ browser = zope.testbrowser.wsgi.Browser()
+ browser.open('http://localhost')
+ self.assertEqual('Hello world!\n', browser.contents)
+ # XXX test for authorization header munging is missing
Property changes on: zope.testbrowser/tags/3.10.3/src/zope/testbrowser/tests/test_wsgi.py
___________________________________________________________________
Added: svn:keywords
+ Id Rev Date
Added: svn:eol-style
+ native
Copied: zope.testbrowser/tags/3.10.3/src/zope/testbrowser/wsgi.py (from rev 119868, zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py)
===================================================================
--- zope.testbrowser/tags/3.10.3/src/zope/testbrowser/wsgi.py (rev 0)
+++ zope.testbrowser/tags/3.10.3/src/zope/testbrowser/wsgi.py 2011-01-24 14:03:18 UTC (rev 119872)
@@ -0,0 +1,129 @@
+##############################################################################
+#
+# Copyright (c) 2010-2011 Zope Foundation 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.
+#
+##############################################################################
+import base64
+import re
+import wsgi_intercept
+import wsgi_intercept.mechanize_intercept
+import zope.testbrowser.browser
+
+
+# List of hostname where the test browser/http function replies to
+TEST_HOSTS = ['localhost', '127.0.0.1']
+
+
+class InterceptBrowser(wsgi_intercept.mechanize_intercept.Browser):
+
+ default_schemes = ['http']
+ default_others = ['_http_error',
+ '_http_default_error']
+ default_features = ['_redirect', '_cookies', '_referer', '_refresh',
+ '_equiv', '_basicauth', '_digestauth']
+
+
+class Browser(zope.testbrowser.browser.Browser):
+ """Override the zope.testbrowser.browser.Browser interface so that it
+ uses InterceptBrowser.
+ """
+
+ def __init__(self, *args, **kw):
+ kw['mech_browser'] = InterceptBrowser()
+ super(Browser, self).__init__(*args, **kw)
+
+
+# Compatibility helpers to behave like zope.app.testing
+
+basicre = re.compile('Basic (.+)?:(.+)?$')
+
+
+def auth_header(header):
+ """This function takes an authorization HTTP header and encode the
+ couple user, password into base 64 like the HTTP protocol wants
+ it.
+ """
+ match = basicre.match(header)
+ if match:
+ u, p = match.group(1, 2)
+ if u is None:
+ u = ''
+ if p is None:
+ p = ''
+ auth = base64.encodestring('%s:%s' % (u, p))
+ return 'Basic %s' % auth[:-1]
+ return header
+
+
+def is_wanted_header(header):
+ """Return True if the given HTTP header key is wanted.
+ """
+ key, value = header
+ return key.lower() not in ('x-content-type-warning', 'x-powered-by')
+
+
+class AuthorizationMiddleware(object):
+ """This middleware makes the WSGI application compatible with the
+ HTTPCaller behavior defined in zope.app.testing.functional:
+ - It modifies the HTTP Authorization header to encode user and
+ password into base64 if it is Basic authentication.
+ """
+
+ def __init__(self, wsgi_stack):
+ self.wsgi_stack = wsgi_stack
+
+ def __call__(self, environ, start_response):
+ # Handle authorization
+ auth_key = 'HTTP_AUTHORIZATION'
+ if auth_key in environ:
+ environ[auth_key] = auth_header(environ[auth_key])
+
+ # Remove unwanted headers
+ def application_start_response(status, headers, exc_info=None):
+ headers = filter(is_wanted_header, headers)
+ start_response(status, headers)
+
+ for entry in self.wsgi_stack(environ, application_start_response):
+ yield entry
+
+
+class Layer(object):
+ """Test layer which sets up WSGI application for use with
+ wsgi_intercept/testbrowser.
+
+ """
+
+ __bases__ = ()
+ __name__ = 'Layer'
+
+ def make_wsgi_app(self):
+ # Override this method in subclasses of this layer in order to set up
+ # the WSGI application.
+ raise NotImplementedError
+
+ def cooperative_super(self, method_name):
+ # Calling `super` for multiple inheritance:
+ method = getattr(super(Layer, self), method_name, None)
+ if method is not None:
+ method()
+
+ def setUp(self):
+ self.cooperative_super('setUp')
+ self.app = self.make_wsgi_app()
+ factory = lambda: AuthorizationMiddleware(self.app)
+
+ for host in TEST_HOSTS:
+ wsgi_intercept.add_wsgi_intercept(host, 80, factory)
+
+ def tearDown(self):
+ for host in TEST_HOSTS:
+ wsgi_intercept.remove_wsgi_intercept(host, 80)
+ self.cooperative_super('tearDown')
More information about the checkins
mailing list