diff options
| author | Chris McDonough <chrism@agendaless.com> | 2008-11-08 07:30:36 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2008-11-08 07:30:36 +0000 |
| commit | 738f325de6fac3551691d07ad0293891fb352b4e (patch) | |
| tree | 774cdef8619c87e7fdfd464bd45e99943178c7bc | |
| parent | deb0dc316b64d5fb7bd0e15a1bafe269d3b33fbc (diff) | |
| download | pyramid-738f325de6fac3551691d07ad0293891fb352b4e.tar.gz pyramid-738f325de6fac3551691d07ad0293891fb352b4e.tar.bz2 pyramid-738f325de6fac3551691d07ad0293891fb352b4e.zip | |
Add makeRequest API.
Add minimal documentation of BFGTestCase.
| -rw-r--r-- | docs/narr/unittesting.rst | 73 | ||||
| -rw-r--r-- | repoze/bfg/testing.py | 49 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_testing.py | 15 |
3 files changed, 128 insertions, 9 deletions
diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst index 0ef04083f..eddae73d9 100644 --- a/docs/narr/unittesting.rst +++ b/docs/narr/unittesting.rst @@ -3,11 +3,72 @@ Unit Testing ============ -:mod:`repoze.bfg` provides helper facilities for writing -``unittest.TestCase`` -derived tests. A base class for these types of -tests as well as functions that help test BFG applications -specifically exist. See the :ref:`testing_module` chapter for the -API. +The suggested mechanism for unit testing :mod:`repoze.bfg` +applications is the Python ``unittest`` module. :mod:`repoze.bfg` +provides a number of facilities that make writing ``unittest`` -based +test cases easier to write. The facilities become particularly useful +when your code calls into :mod:`repoze.bfg` -related framework +functions. -XXX +The ``BFGTestCase`` Base Class +------------------------------ + +The ``repoze.bfg.testing`` module provides a class named +``BFGTestCase`` which you can use as a base class for unittest test +classes. + +.. code-block:: python + :linenos: + + def view_fn(context, request): + from repoze.bfg.chameleon_zpt import render_template_to_response + if 'say' in request.params: + return render_template_to_response('templates/submitted.pt', + say=request.params['say']) + return render_template_to_response('templates/show.pt', say='Hello') + + from repoze.bfg.testing import BFGTestCase + + class MyTest(BFGTestCase): + def test_view_fn_not_submitted(self): + template = self.registerTemplate('templates/show.pt') + request = self.makeRequest() + context = self.makeModel() + response = view_fn(context, request) + self.assertEqual(template.say, 'Hello') + + def test_view_fn_submitted(self): + template = self.registerTemplate('templates/submitted.pt') + request = self.makeRequest() + request.params['say'] = 'Yo' + context = self.makeModel() + response = view_fn(context, request) + self.assertEqual(template.say, 'Yo') + +In the above example, we create a ``MyTest`` test case that inherits +from ``BFGTestCase``. It has two test methods. The first test +method, ``test_view_fn_not_submitted`` tests the ``view_fn`` function +in the case that no "form" values (represented by request.params) have +been submitted. Its first line registers a "template" named +``templates/show.pt`` via the ``registerTemplate`` method (a +``BFGTestCase`` API); this function returns a DummyTemplate instance +which we hang on to for later. We then call ``makeRequest`` to get a +DummyRequest object, and ``makeModel`` to get a DummyModel object. We +call the function being tested with the manufactured context and +request. When the function is called, ``render_template_to_response`` +will call the "dummy" template object instead of the real template +object. When it's called, it will set attributes on itself +corresponding to the non-path keyword arguments provided to the +``render_template_to_response`` function. We check that the ``say`` +parameter sent into the template rendering function was ``Hello`` in +this specific example. The second test, named +``test_view_fn_submitted`` tests the alternate case, where the ``say`` +form value has already been set in the request and performs a similar +template registration and assertion. + +See the :ref:`testing_module` chapter for the entire +:mod:`repoze.bfg` -specific testing API. + +The ``BFGTestCase`` class inherits from ``unittest.TestCase``, so it +will be found by test finders. diff --git a/repoze/bfg/testing.py b/repoze/bfg/testing.py index 2ada3d20e..cfcbc3920 100644 --- a/repoze/bfg/testing.py +++ b/repoze/bfg/testing.py @@ -140,6 +140,19 @@ class BFGTestCase(unittest.TestCase, PlacelessSetup): ``__name__`` attribute that is the value of the key. A dummy model has no other attributes or methods.""" return DummyModel(name, parent) + + def makeRequest(self, path='/', params=None, environ=None, headers=None, + **kw): + """ Returns a ``DummyRequest`` object (mimics a WebOb Request + object) using ``path`` as the path. If ``environ`` is + non-None, it should contain keys that will form the request's + environment. If ``base_url`` is passed in, then the + ``wsgi.url_scheme``, ``HTTP_HOST``, and ``SCRIPT_NAME`` will + be filled in from that value. If ``headers`` is not None, + these will be used as ``request.headers``. The returned + request object will implement the ``repoze.bfg.IRequest`` + interface.""" + return makeRequest(path, params, environ, headers, **kw) def registerUtility(impl, iface, name=''): import zope.component @@ -187,6 +200,39 @@ def registerViewPermission(viewpermission, name, for_=(Interface, Interface)): from repoze.bfg.interfaces import IViewPermission return registerAdapter(viewpermission, for_, IViewPermission, name) +def makeRequest(path, environ=None, base_url=None, headers=None, **kw): + return DummyRequest(path, environ, base_url, headers, **kw) + +from zope.interface import implements +from repoze.bfg.interfaces import IRequest + +class DummyRequest: + implements(IRequest) + def __init__(self, path, params=None, environ=None, headers=None, **kw): + if environ is None: + environ = {} + if params is None: + params = {} + if headers is None: + headers = {} + self.environ = environ + self.headers = headers + self.params = params + self.GET = params + self.POST = params + self.application_url = 'http://example.com' + self.host_url = self.application_url + self.path_url = self.application_url + self.path = path + self.path_info = path + self.script_name = '' + self.path_qs = '' + self.url = self.application_url + self.host = 'example.com:80' + self.body = '' + self.cookies = {} + self.__dict__.update(kw) + class _DummySecurityPolicy: def __init__(self, userid=None, groupids=()): self.userid = userid @@ -270,6 +316,3 @@ class DummyModel: ob = self.subs[name] return ob - - - diff --git a/repoze/bfg/tests/test_testing.py b/repoze/bfg/tests/test_testing.py index 23fbb7cc7..9368a3e5b 100644 --- a/repoze/bfg/tests/test_testing.py +++ b/repoze/bfg/tests/test_testing.py @@ -204,6 +204,21 @@ class TestBFGTestCase(unittest.TestCase, PlacelessSetup): self.assertEqual(model.__name__, 'name') self.assertEqual(model.__parent__, parent) + def test_makeRequest(self): + case = self._makeOne() + request = case.makeRequest('/abc', + params = {'say':'Hello'}, + environ = {'PATH_INFO':'/foo'}, + headers = {'X-Foo':'YUP'}, + water = 1) + self.assertEqual(request.path, '/abc') + self.assertEqual(request.params['say'], 'Hello') + self.assertEqual(request.GET['say'], 'Hello') + self.assertEqual(request.POST['say'], 'Hello') + self.assertEqual(request.headers['X-Foo'], 'YUP') + self.assertEqual(request.environ['PATH_INFO'], '/foo') + self.assertEqual(request.water, 1) + class TestDummyAllowingSecurityPolicy(unittest.TestCase): def _getTargetClass(self): from repoze.bfg.testing import DummyAllowingSecurityPolicy |
