summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-12-19 23:05:23 +0000
committerChris McDonough <chrism@agendaless.com>2009-12-19 23:05:23 +0000
commitf0d12ea82e494c13ce504b73a13c6967ab8fb3e1 (patch)
tree53574884314d3cf8c86494f13e90ce6db5b706a8
parent0adc2fe61c2e225dfa1bcf9a3d814ba394e95ce7 (diff)
downloadpyramid-f0d12ea82e494c13ce504b73a13c6967ab8fb3e1.tar.gz
pyramid-f0d12ea82e494c13ce504b73a13c6967ab8fb3e1.tar.bz2
pyramid-f0d12ea82e494c13ce504b73a13c6967ab8fb3e1.zip
- Add four new testing-related APIs to the
``repoze.bfg.configuration.Configurator`` class: ``testing_securitypolicy``, ``testing_models``, ``testing_add_subscriber``, and ``testing_add_template``. These were added in order to provide more direct access to the functionality of the ``repoze.bfg.testing`` APIs named ``registerDummySecurityPolicy``, ``registerModels``, ``registerEventListener``, and ``registerTemplateRenderer`` when a configurator is used. The ``testing`` APIs named are nominally deprecated (although they will likely remain around "forever", as they are in heavy use in the wild). - Doc-deprecated most helper functions in the ``repoze.bfg.testing`` module. These helper functions likely won't be removed any time soon, nor will they generate a warning any time soon, due to their heavy use in the wild, but equivalent behavior exists in methods of a Configurator.
-rw-r--r--CHANGES.txt24
-rw-r--r--docs/api/configuration.rst11
-rw-r--r--repoze/bfg/configuration.py83
-rw-r--r--repoze/bfg/testing.py83
-rw-r--r--repoze/bfg/tests/test_configuration.py78
-rw-r--r--repoze/bfg/tests/test_testing.py46
6 files changed, 268 insertions, 57 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 5127fc4ed..09f306c9d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,18 @@ Next release
Features
--------
+- Add four new testing-related APIs to the
+ ``repoze.bfg.configuration.Configurator`` class:
+ ``testing_securitypolicy``, ``testing_models``,
+ ``testing_add_subscriber``, and ``testing_add_template``. These
+ were added in order to provide more direct access to the
+ functionality of the ``repoze.bfg.testing`` APIs named
+ ``registerDummySecurityPolicy``, ``registerModels``,
+ ``registerEventListener``, and ``registerTemplateRenderer`` when a
+ configurator is used. The ``testing`` APIs named are nominally
+ deprecated (although they will likely remain around "forever", as
+ they are in heavy use in the wild).
+
- Add a new API to the ``repoze.bfg.configuration.Configurator``
class: ``add_settings``. This API can be used to add "settings"
(information returned within via the
@@ -46,6 +58,18 @@ Internal
directives to use a ``Configurator`` instance and associated
configurator APIs rather than a ZCA registry directly.
+- Remove the ``repoze.bfg.testing.registerTraverser`` function. This
+ function was never an API.
+
+Documenation
+------------
+
+- Doc-deprecated most helper functions in the ``repoze.bfg.testing``
+ module. These helper functions likely won't be removed any time
+ soon, nor will they generate a warning any time soon, due to their
+ heavy use in the wild, but equivalent behavior exists in methods of
+ a Configurator.
+
1.2a6 (2009-12-18)
==================
diff --git a/docs/api/configuration.rst b/docs/api/configuration.rst
index beb86f7ef..95f3a7a4c 100644
--- a/docs/api/configuration.rst
+++ b/docs/api/configuration.rst
@@ -11,6 +11,8 @@
.. automethod:: end
+ .. automethod:: add_adapter
+
.. automethod:: add_renderer(name, factory)
.. automethod:: add_route
@@ -21,6 +23,8 @@
.. automethod:: add_subscriber
+ .. automethod:: add_utility
+
.. automethod:: add_view
.. automethod:: load_zcml(spec)
@@ -35,7 +39,10 @@
.. automethod:: set_notfound_view(view=None, attr=None, renderer=None, wrapper=None)
- .. automethod:: add_adapter
+ .. automethod:: testing_securitypolicy
- .. automethod:: add_utility
+ .. automethod:: testing_models
+
+ .. automethod:: testing_add_subscriber
+ .. automethod:: testing_add_template
diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py
index 8d88c5384..ccfeb7347 100644
--- a/repoze/bfg/configuration.py
+++ b/repoze/bfg/configuration.py
@@ -29,6 +29,8 @@ from repoze.bfg.interfaces import IRouteRequest
from repoze.bfg.interfaces import IRoutesMapper
from repoze.bfg.interfaces import ISecuredView
from repoze.bfg.interfaces import ISettings
+from repoze.bfg.interfaces import ITemplateRenderer
+from repoze.bfg.interfaces import ITraverser
from repoze.bfg.interfaces import IView
from repoze.bfg import chameleon_text
@@ -51,6 +53,7 @@ from repoze.bfg.settings import Settings
from repoze.bfg.static import StaticRootFactory
from repoze.bfg.threadlocal import get_current_registry
from repoze.bfg.threadlocal import manager
+from repoze.bfg.traversal import traversal_path
from repoze.bfg.traversal import DefaultRootFactory
from repoze.bfg.traversal import find_interface
from repoze.bfg.urldispatch import RoutesMapper
@@ -1183,6 +1186,86 @@ class Configurator(object):
view_for=StaticRootFactory,
factory=StaticRootFactory(spec),
_info=_info)
+ # testing API
+
+ def testing_securitypolicy(self, userid=None, groupids=(),
+ permissive=True):
+ """Unit/integration testing helper: registers a a pair of
+ dummy :mod:`repoze.bfg` security policies: an
+ :term:`authorization policy` and an :term:`authentication
+ policy`) using the userid ``userid`` and the group ids
+ ``groupids``. If ``permissive`` is true, a 'permissive'
+ authorization policy is registered; this policy allows all
+ access. If ``permissive`` is false, a nonpermissive
+ authorization policy is registered; this policy denies all
+ access. This function is most useful when testing code that
+ uses the ``repoze.bfg.security`` APIs named
+ ``has_permission``, ``authenticated_userid``,
+ ``effective_principals`` and
+ ``principals_allowed_by_permission``.
+ """
+ from repoze.bfg.testing import DummySecurityPolicy
+ policy = DummySecurityPolicy(userid, groupids, permissive)
+ self.registry.registerUtility(policy, IAuthorizationPolicy)
+ self.registry.registerUtility(policy, IAuthenticationPolicy)
+
+ def testing_models(self, models):
+ """Unit/integration testing helper: registers a dictionary of
+ models that can be resolved via
+ ``repoze.bfg.traversal.find_model``. This is most useful for
+ testing code that wants to call the
+ ``repoze.bfg.traversal.find_model`` API. The ``find_model``
+ API is called with a path as one of its arguments. If the
+ dictionary you register when calling this method contains that
+ path as a string key (e.g. ``/foo/bar`` or ``foo/bar``), the
+ corresponding value will be returned to ``find_model`` (and
+ thus to your code) when ``find_model`` is called with an
+ equivalent path string or tuple."""
+ class DummyTraverserFactory:
+ def __init__(self, context):
+ self.context = context
+
+ def __call__(self, request):
+ path = request['PATH_INFO']
+ ob = models[path]
+ traversed = traversal_path(path)
+ return {'context':ob, 'view_name':'','subpath':(),
+ 'traversed':traversed, 'virtual_root':ob,
+ 'virtual_root_path':(), 'root':ob}
+ self.registry.registerAdapter(DummyTraverserFactory, (Interface,),
+ ITraverser)
+ return models
+
+ def testing_add_subscriber(self, event_iface=Interface):
+ """Unit/integration testing helper: Registers a
+ :term:`subscriber` listening for events of the type
+ ``event_iface`` and returns a list which is appended to by the
+ subscriber. When an event is dispatched that matches
+ ``event_iface``, that event will be appended to the list. You
+ can then compare the values in the list to expected event
+ notifications. This method is useful when testing code that
+ wants to call ``registry.notify``,
+ ``zope.component.event.dispatch`` or
+ ``zope.component.event.objectEventNotify``.
+ """
+ L = []
+ def subscriber(*event):
+ L.extend(event)
+ self.add_subscriber(subscriber, event_iface)
+ return L
+
+ def testing_add_template(self, path, renderer=None):
+ """ Register a template tenderer at ``path`` (usually a relative
+ filename ala ``templates/foo.pt``) and return the renderer object.
+ If the ``renderer`` argument is None, a 'dummy' renderer will be
+ used. This function is useful when testing code that calls the
+ ``render_template_to_response`` or any other ``render_template*``
+ API of any of the built-in templating systems."""
+ from repoze.bfg.testing import DummyTemplateRenderer
+ if renderer is None:
+ renderer = DummyTemplateRenderer()
+ self.registry.registerUtility(renderer, ITemplateRenderer, path)
+ return renderer
def _make_predicates(xhr=None, request_method=None, path_info=None,
request_param=None, header=None, accept=None,
diff --git a/repoze/bfg/testing.py b/repoze/bfg/testing.py
index 5d0a756e7..cd43c297e 100644
--- a/repoze/bfg/testing.py
+++ b/repoze/bfg/testing.py
@@ -10,14 +10,10 @@ from zope.interface import implements
from zope.interface import Interface
from zope.interface import alsoProvides
-from repoze.bfg.interfaces import IAuthenticationPolicy
-from repoze.bfg.interfaces import IAuthorizationPolicy
from repoze.bfg.interfaces import IRequest
from repoze.bfg.interfaces import IRoutesMapper
from repoze.bfg.interfaces import ISecuredView
from repoze.bfg.interfaces import ISettings
-from repoze.bfg.interfaces import ITemplateRenderer
-from repoze.bfg.interfaces import ITraverser
from repoze.bfg.interfaces import IView
from repoze.bfg.interfaces import IViewPermission
@@ -32,7 +28,6 @@ from repoze.bfg.security import has_permission
from repoze.bfg.settings import Settings
from repoze.bfg.threadlocal import get_current_registry
from repoze.bfg.threadlocal import manager
-from repoze.bfg.traversal import traversal_path
from repoze.bfg.urldispatch import RoutesMapper
from repoze.bfg.zcml import zcml_configure # API
@@ -52,11 +47,15 @@ def registerDummySecurityPolicy(userid=None, groupids=(), permissive=True):
``repoze.bfg.security`` APIs named ``has_permission``,
``authenticated_userid``, ``effective_principals``,
``principals_allowed_by_permission``, and so on.
+
+ .. warning:: This API is deprecated as of :mod:`repoze.bfg` 1.2.
+ Instead use the ``testing_securitypolicy`` method of a
+ :term:`Configurator` in your unit and integration tests.
"""
- policy = DummySecurityPolicy(userid, groupids, permissive)
- reg = get_current_registry()
- reg.registerUtility(policy, IAuthorizationPolicy)
- reg.registerUtility(policy, IAuthenticationPolicy)
+ registry = get_current_registry()
+ config = Configurator(registry=registry)
+ return config.testing_securitypolicy(userid=userid, groupids=groupids,
+ permissive=permissive)
def registerModels(models):
""" Registers a dictionary of models that can be resolved via
@@ -68,21 +67,15 @@ def registerModels(models):
string key (e.g. ``/foo/bar`` or ``foo/bar``), the corresponding
value will be returned to ``find_model`` (and thus to your code)
when ``find_model`` is called with an equivalent path string or
- tuple."""
- class DummyTraverserFactory:
- def __init__(self, context):
- self.context = context
-
- def __call__(self, request):
- path = request['PATH_INFO']
- ob = models[path]
- traversed = traversal_path(path)
- return {'context':ob, 'view_name':'','subpath':(),
- 'traversed':traversed, 'virtual_root':ob,
- 'virtual_root_path':(), 'root':ob}
-
- registerTraverser(DummyTraverserFactory)
- return models
+ tuple.
+
+ .. warning:: This API is deprecated as of :mod:`repoze.bfg` 1.2.
+ Instead use the ``testing_models`` method of a
+ :term:`Configurator` in your unit and integration tests.
+ """
+ registry = get_current_registry()
+ config = Configurator(registry=registry)
+ return config.testing_models(models)
def registerEventListener(event_iface=Interface):
""" Registers an :term:`event` listener (aka :term:`subscriber`)
@@ -94,12 +87,14 @@ def registerEventListener(event_iface=Interface):
testing code that wants to call ``registry.notify``,
``zope.component.event.dispatch`` or
``zope.component.event.objectEventNotify``.
+
+ .. warning:: This API is deprecated as of :mod:`repoze.bfg` 1.2.
+ Instead use the ``testing_add_subscriber`` method of a
+ :term:`Configurator` in your unit and integration tests.
"""
- L = []
- def subscriber(*event):
- L.extend(event)
- registerSubscriber(subscriber, event_iface)
- return L
+ registry = get_current_registry()
+ config = Configurator(registry=registry)
+ return config.testing_add_subscriber(event_iface)
def registerTemplateRenderer(path, renderer=None):
""" Register a template tenderer at ``path`` (usually a relative
@@ -107,10 +102,16 @@ def registerTemplateRenderer(path, renderer=None):
If the ``renderer`` argument is None, a 'dummy' renderer will be
used. This function is useful when testing code that calls the
``render_template_to_response`` or any other ``render_template*``
- API of any of the built-in templating systems."""
- if renderer is None:
- renderer = DummyTemplateRenderer()
- return registerUtility(renderer, ITemplateRenderer, path)
+ API of any of the built-in templating systems.
+
+ .. warning:: This API is deprecated as of :mod:`repoze.bfg` 1.2.
+ Instead use the ``testing_add_template`` method of a
+ :term:`Configurator` in your unit and integration tests.
+
+ """
+ registry = get_current_registry()
+ config = Configurator(registry=registry)
+ return config.testing_add_template(path, renderer)
# registerDummyRenderer is a deprecated alias that should never be removed
# (far too much usage in the wild)
@@ -249,14 +250,9 @@ def registerSubscriber(subscriber, iface=Interface):
Instead use the ``add_subscriber`` method of a
:term:`Configurator` in your unit and integration tests.
"""
- reg = get_current_registry()
- if not isinstance(iface, (tuple, list)):
- iface = (iface,)
- reg.registerHandler(subscriber, iface)
- return subscriber
-
-def registerTraverser(traverser, for_=Interface):
- return registerAdapter(traverser, for_, ITraverser)
+ registry = get_current_registry()
+ config = Configurator(registry)
+ return config.add_subscriber(subscriber, iface=iface)
def registerRoute(path, name, factory=None):
""" Register a new :term:`route` using a path
@@ -296,6 +292,11 @@ def registerRoutesMapper(root_factory=None):
``repoze.bfg.testing.registerRoute``.
.. note:: This API was added in :mod:`repoze.bfg` version 1.1.
+
+ .. warning:: This API is not useful in :mod:`repoze.bfg` 1.2 or better
+ because a route mapper is no longer required to be
+ present for successful operation of the system without
+ any routes present.
"""
mapper = RoutesMapper()
reg = get_current_registry()
diff --git a/repoze/bfg/tests/test_configuration.py b/repoze/bfg/tests/test_configuration.py
index 9c48cc010..a303f550f 100644
--- a/repoze/bfg/tests/test_configuration.py
+++ b/repoze/bfg/tests/test_configuration.py
@@ -1864,6 +1864,81 @@ class ConfiguratorTests(unittest.TestCase):
result = config.registry.queryUtility(IDummy, name='foo')
self.assertEqual(result, 'OK')
+ def test_testing_securitypolicy(self):
+ from repoze.bfg.testing import DummySecurityPolicy
+ config = self._makeOne()
+ config.testing_securitypolicy('user', ('group1', 'group2'),
+ permissive=False)
+ from repoze.bfg.interfaces import IAuthenticationPolicy
+ from repoze.bfg.interfaces import IAuthorizationPolicy
+ ut = config.registry.getUtility(IAuthenticationPolicy)
+ self.failUnless(isinstance(ut, DummySecurityPolicy))
+ ut = config.registry.getUtility(IAuthorizationPolicy)
+ self.assertEqual(ut.userid, 'user')
+ self.assertEqual(ut.groupids, ('group1', 'group2'))
+ self.assertEqual(ut.permissive, False)
+
+ def test_testing_models(self):
+ from repoze.bfg.traversal import find_model
+ from repoze.bfg.interfaces import ITraverser
+ ob1 = object()
+ ob2 = object()
+ models = {'/ob1':ob1, '/ob2':ob2}
+ config = self._makeOne()
+ config.testing_models(models)
+ adapter = config.registry.getAdapter(None, ITraverser)
+ result = adapter({'PATH_INFO':'/ob1'})
+ self.assertEqual(result['context'], ob1)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (u'ob1',))
+ self.assertEqual(result['virtual_root'], ob1)
+ self.assertEqual(result['virtual_root_path'], ())
+ result = adapter({'PATH_INFO':'/ob2'})
+ self.assertEqual(result['context'], ob2)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (u'ob2',))
+ self.assertEqual(result['virtual_root'], ob2)
+ self.assertEqual(result['virtual_root_path'], ())
+ self.assertRaises(KeyError, adapter, {'PATH_INFO':'/ob3'})
+ try:
+ config.begin()
+ self.assertEqual(find_model(None, '/ob1'), ob1)
+ finally:
+ config.end()
+
+ def test_testing_add_subscriber_single(self):
+ config = self._makeOne()
+ L = config.testing_add_subscriber(IDummy)
+ event = DummyEvent()
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
+ def test_testing_add_subscriber_multiple(self):
+ config = self._makeOne()
+ L = config.testing_add_subscriber((Interface, IDummy))
+ event = DummyEvent()
+ event.object = 'foo'
+ # the below is the equivalent of z.c.event.objectEventNotify(event)
+ config.registry.subscribers((event.object, event), None)
+ self.assertEqual(len(L), 2)
+ self.assertEqual(L[0], 'foo')
+ self.assertEqual(L[1], event)
+
+ def test_testing_add_subscriber_defaults(self):
+ config = self._makeOne()
+ L = config.testing_add_subscriber()
+ event = object()
+ config.registry.notify(event)
+ self.assertEqual(L[-1], event)
+ event2 = object()
+ config.registry.notify(event2)
+ self.assertEqual(L[-1], event2)
+
class Test__map_view(unittest.TestCase):
def setUp(self):
from repoze.bfg.registry import Registry
@@ -2872,3 +2947,6 @@ class DummyFactory(object):
def __call__(self):
""" """
+class DummyEvent:
+ implements(IDummy)
+
diff --git a/repoze/bfg/tests/test_testing.py b/repoze/bfg/tests/test_testing.py
index 72ecd96b0..4762eda19 100644
--- a/repoze/bfg/tests/test_testing.py
+++ b/repoze/bfg/tests/test_testing.py
@@ -221,28 +221,32 @@ class Test_registerView(TestBase):
class Test_registerAdapter(TestBase):
def test_registerAdapter(self):
- from zope.interface import implements
from zope.interface import Interface
class provides(Interface):
pass
class Provider:
- implements(provides)
- def __init__(self, context, request):
- self.context = context
- self.request = request
+ pass
class for_(Interface):
pass
- class For_:
- implements(for_)
- for1 = For_()
- for2 = For_()
from repoze.bfg import testing
testing.registerAdapter(Provider, (for_, for_), provides, name='foo')
- adapter = self.registry.getMultiAdapter(
- (for1, for2), provides, name='foo')
- self.failUnless(isinstance(adapter, Provider))
- self.assertEqual(adapter.context, for1)
- self.assertEqual(adapter.request, for2)
+ adapter = self.registry.adapters.lookup(
+ (for_, for_), provides, name='foo')
+ self.assertEqual(adapter, Provider)
+
+ def test_registerAdapter_notlist(self):
+ from zope.interface import Interface
+ class provides(Interface):
+ pass
+ class Provider:
+ pass
+ class for_(Interface):
+ pass
+ from repoze.bfg import testing
+ testing.registerAdapter(Provider, for_, provides, name='foo')
+ adapter = self.registry.adapters.lookup(
+ (for_,), provides, name='foo')
+ self.assertEqual(adapter, Provider)
class Test_registerUtility(TestBase):
def test_registerUtility(self):
@@ -259,6 +263,20 @@ class Test_registerUtility(TestBase):
testing.registerUtility(utility, iface, name='mudge')
self.assertEqual(self.registry.getUtility(iface, name='mudge')(), 'foo')
+class Test_registerSubscriber(TestBase):
+ def test_it(self):
+ from repoze.bfg import testing
+ L = []
+ def subscriber(event):
+ L.append(event)
+ testing.registerSubscriber(subscriber, iface=IDummy)
+ event = DummyEvent()
+ self.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ self.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
class Test_registerRoute(TestBase):
def test_registerRoute(self):
from repoze.bfg.url import route_url