From fec0f0614c69dc7382fba367f8269479e2682058 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 25 Oct 2010 18:47:29 -0400 Subject: convert narrative docs to Pyramid --- docs/narr/unittesting.rst | 106 +++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 53 deletions(-) (limited to 'docs/narr/unittesting.rst') diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst index a8005888f..d6f854187 100644 --- a/docs/narr/unittesting.rst +++ b/docs/narr/unittesting.rst @@ -46,15 +46,15 @@ measure of assurance that your "units" work together, as they will be expected to when your application is run in production. The suggested mechanism for unit and integration testing of a -:mod:`repoze.bfg` application is the Python :mod:`unittest` module. +:mod:`pyramid` application is the Python :mod:`unittest` module. Although this module is named :mod:`unittest`, it is actually capable of driving both unit and integration tests. A good :mod:`unittest` tutorial is available within `Dive Into Python `_ by Mark Pilgrim. -:mod:`repoze.bfg` provides a number of facilities that make unit and +:mod:`pyramid` provides a number of facilities that make unit and integration tests easier to write. The facilities become particularly -useful when your code calls into :mod:`repoze.bfg` -related framework +useful when your code calls into :mod:`pyramid` -related framework functions. .. index:: @@ -67,16 +67,16 @@ functions. Test Set Up and Tear Down -------------------------- -:mod:`repoze.bfg` uses a "global" (actually :term:`thread local`) data +:mod:`pyramid` uses a "global" (actually :term:`thread local`) data structure to hold on to two items: the current :term:`request` and the current :term:`application registry`. These data structures are -available via the :func:`repoze.bfg.threadlocal.get_current_request` -and :func:`repoze.bfg.threadlocal.get_current_registry` functions, +available via the :func:`pyramid.threadlocal.get_current_request` +and :func:`pyramid.threadlocal.get_current_registry` functions, respectively. See :ref:`threadlocals_chapter` for information about these functions and the data structures they return. If your code uses these ``get_current_*`` functions or calls -:mod:`repoze.bfg` code which uses ``get_current_*`` functions, you +:mod:`pyramid` code which uses ``get_current_*`` functions, you will need to construct a :term:`Configurator` and call its ``begin`` method within the ``setUp`` method of your unit test and call the same configurator's ``end`` method within the ``tearDown`` method of your @@ -91,7 +91,7 @@ of a single test. Here's an example of using this feature: :linenos: import unittest - from repoze.bfg.configuration import Configurator + from pyramid.configuration import Configurator class MyTest(unittest.TestCase): def setUp(self): @@ -102,31 +102,31 @@ of a single test. Here's an example of using this feature: self.config.end() The above will make sure that -:func:`repoze.bfg.threadlocal.get_current_registry` will return the +:func:`pyramid.threadlocal.get_current_registry` will return the :term:`application registry` associated with the ``config`` Configurator instance when -:func:`repoze.bfg.threadlocal.get_current_registry` is called in a +:func:`pyramid.threadlocal.get_current_registry` is called in a test case method attached to ``MyTest``. Each test case method attached to ``MyTest`` will use an isolated registry. -The :meth:`repoze.bfg.configuration.Configurator.begin` method accepts +The :meth:`pyramid.configuration.Configurator.begin` method accepts various arguments that influence the code run during the test. See the :ref:`configuration_module` chapter for information about the API of a :term:`Configurator`, including its ``begin`` and ``end`` methods. -If you also want to make :func:`repoze.bfg.get_current_request` +If you also want to make :func:`pyramid.get_current_request` return something other than ``None`` during the course of a single test, you can pass a :term:`request` object into the -:meth:`repoze.bfg.configuration.Configurator.begin` method of the +:meth:`pyramid.configuration.Configurator.begin` method of the Configurator within the ``setUp`` method of your test: .. code-block:: python :linenos: import unittest - from repoze.bfg.configuration import Configurator - from repoze.bfg import testing + from pyramid.configuration import Configurator + from pyramid import testing class MyTest(unittest.TestCase): def setUp(self): @@ -140,12 +140,12 @@ Configurator within the ``setUp`` method of your test: If you pass a :term:`request` object into the ``begin`` method of the configurator within your test case's ``setUp``, any test method attached to the ``MyTest`` test case that directly or indirectly calls -:func:`repoze.bfg.threadlocal.get_current_request` will receive the +:func:`pyramid.threadlocal.get_current_request` will receive the request you passed into the ``begin`` method. Otherwise, during -testing, :func:`repoze.bfg.threadlocal.get_current_request` will +testing, :func:`pyramid.threadlocal.get_current_request` will return ``None``. We use a "dummy" request implementation supplied by -:class:`repoze.bfg.testing.DummyRequest` because it's easier to -construct than a "real" :mod:`repoze.bfg` request object. +:class:`pyramid.testing.DummyRequest` because it's easier to +construct than a "real" :mod:`pyramid` request object. What? ~~~~~ @@ -153,8 +153,8 @@ What? Thread local data structures are always a bit confusing, especially when they're used by frameworks. Sorry. So here's a rule of thumb: if you don't *know* whether you're calling code that uses the -:func:`repoze.bfg.threadlocal.get_current_registry` or -:func:`repoze.bfg.threadlocal.get_current_request` functions, or you +:func:`pyramid.threadlocal.get_current_registry` or +:func:`pyramid.threadlocal.get_current_request` functions, or you don't care about any of this, but you still want to write test code, just always create a Configurator instance and call its ``begin`` method within the ``setUp`` of a unit test, then subsequently call its @@ -163,27 +163,27 @@ anything if the application you're testing does not call any ``get_current*`` function. .. index:: - single: repoze.bfg.testing + single: pyramid.testing single: Configurator testing API -Using the ``Configurator`` and ``repoze.bfg.testing`` APIs in Unit Tests +Using the ``Configurator`` and ``pyramid.testing`` APIs in Unit Tests ------------------------------------------------------------------------ -The ``Configurator`` API and the ``repoze.bfg.testing`` module +The ``Configurator`` API and the ``pyramid.testing`` module provide a number of functions which can be used during unit testing. These functions make :term:`configuration declaration` calls to the current :term:`application registry`, but typically register a "stub" or "dummy" feature in place of the "real" feature that the code would call if it was being run normally. -For example, let's imagine you want to unit test a :mod:`repoze.bfg` +For example, let's imagine you want to unit test a :mod:`pyramid` view function. .. code-block:: python :linenos: def view_fn(request): - from repoze.bfg.chameleon_zpt import render_template_to_response + from pyramid.chameleon_zpt import render_template_to_response if 'say' in request.params: return render_template_to_response('templates/submitted.pt', say=request.params['say']) @@ -191,17 +191,17 @@ view function. Without invoking any startup code or using the testing API, an attempt to run this view function in a unit test will result in an error. -When a :mod:`repoze.bfg` application starts normally, it will populate +When a :mod:`pyramid` application starts normally, it will populate a :term:`application registry` using :term:`configuration declaration` calls made against a :term:`Configurator` (sometimes deferring to the application's ``configure.zcml`` :term:`ZCML` file via ``load_zcml``). But if this application registry is not created and populated -(e.g. with an :meth:`repoze.bfg.configuration.Configurator.add_view` +(e.g. with an :meth:`pyramid.configuration.Configurator.add_view` :term:`configuration declaration` or ``view`` declarations in :term:`ZCML`), like when you invoke application code via a unit test, -:mod:`repoze.bfg` API functions will tend to fail. +:mod:`pyramid` API functions will tend to fail. -The testing API provided by :mod:`repoze.bfg` allows you to simulate +The testing API provided by :mod:`pyramid` allows you to simulate various application registry registrations for use under a unit testing framework without needing to invoke the actual application configuration implied by its ``run.py``. For example, if you wanted @@ -213,8 +213,8 @@ used the testing API. :linenos: import unittest - from repoze.bfg.configuration import Configurator - from repoze.bfg import testing + from pyramid.configuration import Configurator + from pyramid import testing class MyTest(unittest.TestCase): def setUp(self): @@ -241,7 +241,7 @@ used the testing API. renderer.assert_(say='Yo') In the above example, we create a ``MyTest`` test case that inherits -from :mod:`unittest.TestCase`. If it's in our :mod:`repoze.bfg` +from :mod:`unittest.TestCase`. If it's in our :mod:`pyramid` application, it will be found when ``setup.py test`` is run. It has two test methods. @@ -249,23 +249,23 @@ 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 "dummy template renderer" named ``templates/show.pt`` via the -:meth:`repoze.bfg.configuration.Configurator.testing_add_template` +:meth:`pyramid.configuration.Configurator.testing_add_template` method; this method returns a -:class:`repoze.bfg.testing.DummyTemplateRenderer` instance which we +:class:`pyramid.testing.DummyTemplateRenderer` instance which we hang on to for later. -We then create a :class:`repoze.bfg.testing.DummyRequest` object which +We then create a :class:`pyramid.testing.DummyRequest` object which simulates a WebOb request object API. A -:class:`repoze.bfg.testing.DummyRequest` is a request object that -requires less setup than a "real" :mod:`repoze.bfg` request. We call +:class:`pyramid.testing.DummyRequest` is a request object that +requires less setup than a "real" :mod:`pyramid` request. We call the function being tested with the manufactured request. When the function is called, -:func:`repoze.bfg.chameleon_zpt.render_template_to_response` will call +:func:`pyramid.chameleon_zpt.render_template_to_response` will call the "dummy" template renderer object instead of the real template renderer object. When the dummy renderer is called, it will set attributes on itself corresponding to the non-path keyword arguments provided to the -:func:`repoze.bfg.chameleon_zpt.render_template_to_response` function. +:func:`pyramid.chameleon_zpt.render_template_to_response` function. We check that the ``say`` parameter sent into the template rendering function was ``Hello`` in this specific example. The ``assert_`` method of the renderer we've created will raise an @@ -281,15 +281,15 @@ attribute is ``Yo``, as this is what is expected of the view function in the branch it's testing. Note that the test calls the -:meth:`repoze.bfg.configuration.Configurator.begin` method in its +:meth:`pyramid.configuration.Configurator.begin` method in its ``setUp`` method and the ``end`` method of the same in its ``tearDown`` method. If you use any of the -:class:`repoze.bfg.configuration.Configurator` APIs during testing, be +:class:`pyramid.configuration.Configurator` APIs during testing, be sure to use this pattern in your test case's ``setUp`` and ``tearDown``; these methods make sure you're using a "fresh" :term:`application registry` per test run. -See the :ref:`testing_module` chapter for the entire :mod:`repoze.bfg` +See the :ref:`testing_module` chapter for the entire :mod:`pyramid` -specific testing API. This chapter describes APIs for registering a security policy, registering models at paths, registering event listeners, registering views and view permissions, and classes @@ -306,22 +306,22 @@ See also the various methods of the :term:`Configurator` documented in Creating Integration Tests -------------------------- -In :mod:`repoze.bfg`, a *unit test* typically relies on "mock" or +In :mod:`pyramid`, a *unit test* typically relies on "mock" or "dummy" implementations to give the code under test only enough context to run. "Integration testing" implies another sort of testing. In the context -of a :mod:`repoze.bfg`, integration test, the test logic tests the +of a :mod:`pyramid`, integration test, the test logic tests the functionality of some code *and* its integration with the rest of the -:mod:`repoze.bfg` framework. +:mod:`pyramid` framework. -In :mod:`repoze.bfg` applications that use :term:`ZCML`, you can +In :mod:`pyramid` applications that use :term:`ZCML`, you can create an integration test by *loading its ZCML* in the test's setup -code. This causes the entire :mod:`repoze.bfg` environment to be set +code. This causes the entire :mod:`pyramid` environment to be set up and torn down as if your application was running "for real". This is a heavy-hammer way of making sure that your tests have enough context to run properly, and it tests your code's integration with the -rest of :mod:`repoze.bfg`. +rest of :mod:`pyramid`. Let's demonstrate this by showing an integration test for a view. The below test assumes that your application's package name is ``myapp``, @@ -335,14 +335,14 @@ environment. import unittest - from repoze.bfg.configuration import Configurator - from repoze.bfg import testing + from pyramid.configuration import Configurator + from pyramid import testing class ViewIntegrationTests(unittest.TestCase): def setUp(self): """ This sets up the application registry with the registrations your application declares in its configure.zcml - (including dependent registrations for repoze.bfg itself). + (including dependent registrations for pyramid itself). """ import myapp self.config = Configurator(package=myapp) @@ -367,7 +367,7 @@ environment. str(len(body)))) Unless you cannot avoid it, you should prefer writing unit tests that -use the :class:`repoze.bfg.configuration,Configurator` API to set up +use the :class:`pyramid.configuration,Configurator` API to set up the right "mock" registrations rather than creating an integration test. Unit tests will run faster (because they do less for each test) and the result of a unit test is usually easier to make assertions -- cgit v1.2.3