Skip to content

Commit

Permalink
Remove zope.app.wsgi dependency by re-implementing the test applicati…
Browse files Browse the repository at this point in the history
…on as a

pure WebOb based application.

Currently the application needs to do some gymnastics to be 100% compatible
with the existing tests. In a 3rd branch, I'll remove the gymnastics by
refactoring the existing tests.
  • Loading branch information
Brian Sutherland committed Jan 17, 2011
1 parent 3297d14 commit 0d9ebec
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 12 deletions.
1 change: 0 additions & 1 deletion setup.py
Expand Up @@ -58,7 +58,6 @@
extras_require = {
'test': [
'WebTest',
'zope.app.wsgi',
'zope.browserpage',
'zope.browserresource',
'zope.component',
Expand Down
144 changes: 144 additions & 0 deletions src/zope/testbrowser/ftests/wsgitestapp.py
@@ -0,0 +1,144 @@
##############################################################################
#
# Copyright (c) 2010 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.
#
##############################################################################
"""A minimal WSGI application used as a test fixture."""

import os
import mimetypes
from datetime import datetime

from webob import Request, Response
from zope.pagetemplate.pagetemplatefile import PageTemplateFile

from zope.testbrowser import ftests

class NotFound(Exception):

def __init__(self, ob, name):
self.ob = ob
self.name = name

def __str__(self):
return 'Object: %s, name: %r' % (self.ob, self.name)


class ZopeRequestAdapter(object):
"""Adapt a webob request into enough of a zope.publisher request for the tests to pass"""

def __init__(self, request, response=None):
self._request = request
self._response = response

@property
def form(self):
return self._request.params

def __getitem__(self, name):
return self._request.params[name]

_HERE = os.path.dirname(__file__)

class MyPageTemplateFile(PageTemplateFile):

def pt_getContext(self, args, *extra_args, **kw):
request = args[0]
namespace = super(MyPageTemplateFile, self).pt_getContext(args, *extra_args, **kw)
namespace['request'] = request
return namespace

class WSGITestApplication(object):

def __call__(self, environ, start_response):
req = Request(environ)
handler = {'/set_status.html': set_status,
'/@@echo.html': echo,
'/echo_one.html': echo_one,
'/set_cookie.html': set_cookie,
'/get_cookie.html': get_cookie,
'/inner/set_cookie.html': set_cookie,
'/inner/get_cookie.html': get_cookie,
'/inner/path/set_cookie.html': set_cookie,
'/inner/path/get_cookie.html': get_cookie,
}.get(req.path_info)
if handler is None and req.path_info.startswith('/@@/testbrowser/'):
handler = handle_resource
if handler is None:
handler = handle_notfound
try:
resp = handler(req)
except Exception, exc:
if not environ.get('wsgi.handleErrors', True):
raise
resp = Response()
resp.status = {NotFound: 404}.get(type(exc), 500)
resp.headers.add('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)')
return resp(environ, start_response)

def handle_notfound(req):
raise NotFound('<WSGI application>', unicode(req.path_info[1:]))

def handle_resource(req):
filename = req.path_info.split('/')[-1]
type, _ = mimetypes.guess_type(filename)
path = os.path.join(_HERE, filename)
if type == 'text/html':
pt = MyPageTemplateFile(path)
zreq = ZopeRequestAdapter(req)
contents = pt(zreq)
else:
contents = open(path, 'r').read()
return Response(contents, content_type=type)

def get_cookie(req):
cookies = ['%s: %s' % i for i in sorted(req.cookies.items())]
return Response('\n'.join(cookies))

def set_cookie(req):
cookie_parms = {'path': None}
cookie_parms.update(dict((str(k), str(v)) for k, v in req.params.items()))
name = cookie_parms.pop('name')
value = cookie_parms.pop('value')
if 'max-age' in cookie_parms:
cookie_parms['max_age'] = int(cookie_parms.pop('max-age'))
if 'expires' in cookie_parms:
cookie_parms['expires'] = datetime.strptime(cookie_parms.pop('expires'), '%a, %d %b %Y %H:%M:%S GMT')
resp = Response()
resp.set_cookie(name, value, **cookie_parms)
return resp

def echo(req):
items = []
for k in ftests._interesting_environ:
v = req.environ.get(k, None)
if v is None:
continue
items.append('%s: %s' % (k, v))
items.extend('%s: %s' % x for x in sorted(req.params.items()))
if req.method == 'POST' and req.content_type == 'application/x-www-form-urlencoded':
body = ''
else:
body = req.body
items.append('Body: %r' % body)
return Response('\n'.join(items))

def echo_one(req):
resp = repr(req.environ.get(req.params['var']))
return Response(resp)

def set_status(req):
status = req.params.get('status')
if status:
resp = Response('Just set a status of %s' % status)
resp.status = int(status)
return resp
return Response('Everything fine')
29 changes: 18 additions & 11 deletions src/zope/testbrowser/tests.py
Expand Up @@ -24,14 +24,14 @@
import sys

from webtest import TestApp
from zope.app.wsgi import WSGIPublisherApplication
from zope.app.testing.functional import FunctionalDocFileSuite
import zope.app.testing.functional
import zope.testing.renormalizing

import zope.testbrowser.browser
from zope.testbrowser.testing import Browser as TestingBrowser
from zope.testbrowser.wsgi import Browser as WSGIBrowser
from zope.testbrowser.ftests.wsgitestapp import WSGITestApplication

def set_next_response(body, headers=None, status='200', reason='OK'):
global next_response_body
Expand Down Expand Up @@ -462,6 +462,12 @@ def sub(self, replacement, text):
(re.compile(r'Host: localhost'), 'Connection: close'),
(re.compile(r'Content-Type: '), 'Content-type: '),
(re.compile(r'Content-Disposition: '), 'Content-disposition: '),
(re.compile(r'; charset=UTF-8'), ';charset=utf-8'),
# webtest quotes cookies differently to zope.publisher
(re.compile(r'\'comment\': \'"silly billy"\','), "'comment': 'silly%20billy',"),
# webtest seems to expire cookies one second before the date set in set_cookie
(re.compile(r"'expires': datetime.datetime\(2029, 12, 31, 23, 59, 59, tzinfo=<UTC>\),"), "'expires': datetime.datetime(2030, 1, 1, 0, 0, tzinfo=<UTC>),"),
(re.compile(r"Object: <WSGI application>,"), "Object: <zope.site.folder.Folder object at ...>,"),
])

TestBrowserLayer = zope.app.testing.functional.ZCMLLayer(
Expand Down Expand Up @@ -497,26 +503,27 @@ def test_suite():

# re-run the above tests using the WSGI connectior
def make_browser(*args, **kw):
app = WSGIPublisherApplication(TestBrowserLayer.setup.db)
app = WSGITestApplication()
test_app = TestApp(app)
return WSGIBrowser(test_app, *args, **kw)
globals = dict(Browser=make_browser)

readme = FunctionalDocFileSuite('README.txt', optionflags=flags,
readme = doctest.DocFileSuite('README.txt', optionflags=flags,
checker=checker, globs=globals)
readme.layer = TestBrowserLayer

cookies = FunctionalDocFileSuite('cookies.txt', optionflags=flags,
checker=checker, globs=globals)
cookies.layer = TestBrowserLayer
def setUp(test):
root = {}
def fakeGetRootFolder():
return root
test.globs['getRootFolder'] = fakeGetRootFolder
cookies = doctest.DocFileSuite('cookies.txt', optionflags=flags,
checker=checker, globs=globals, setUp=setUp)

fixed_bugs = FunctionalDocFileSuite('fixed-bugs.txt', optionflags=flags,
fixed_bugs = doctest.DocFileSuite('fixed-bugs.txt', optionflags=flags,
globs=globals)
fixed_bugs.layer = TestBrowserLayer

wsgi = FunctionalDocFileSuite('wsgi.txt', optionflags=flags,
wsgi = doctest.DocFileSuite('wsgi.txt', optionflags=flags,
checker=checker, globs=globals)
wsgi.layer = TestBrowserLayer

tests.extend([readme, cookies, fixed_bugs, wsgi])

Expand Down

0 comments on commit 0d9ebec

Please sign in to comment.