summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorTres Seaver <tseaver@palladion.com>2014-11-26 14:59:20 -0500
committerTres Seaver <tseaver@palladion.com>2014-11-26 14:59:20 -0500
commite9189222be26d7b4979f5af12efa3a269835a332 (patch)
treeaa2d045d7fc12556ee92473421587950b4d7a241 /docs
parent782eb470cf4b31c2cab75f3cc14a5f9c42eeb9f0 (diff)
parent9c94e129f1bbb753317deba7ea5f790db13e0709 (diff)
downloadpyramid-e9189222be26d7b4979f5af12efa3a269835a332.tar.gz
pyramid-e9189222be26d7b4979f5af12efa3a269835a332.tar.bz2
pyramid-e9189222be26d7b4979f5af12efa3a269835a332.zip
Merge pull request #1467 from mgrbyte/fix.issue1001
Include code examples for integration and functional tests in docs.
Diffstat (limited to 'docs')
-rw-r--r--docs/narr/MyProject/myproject/tests.py37
-rw-r--r--docs/narr/MyProject/setup.py45
-rw-r--r--docs/narr/testing.rst142
3 files changed, 131 insertions, 93 deletions
diff --git a/docs/narr/MyProject/myproject/tests.py b/docs/narr/MyProject/myproject/tests.py
index 64dcab1d5..8c60407e5 100644
--- a/docs/narr/MyProject/myproject/tests.py
+++ b/docs/narr/MyProject/myproject/tests.py
@@ -15,3 +15,40 @@ class ViewTests(unittest.TestCase):
request = testing.DummyRequest()
info = my_view(request)
self.assertEqual(info['project'], 'MyProject')
+
+class ViewIntegrationTests(unittest.TestCase):
+ def setUp(self):
+ """ This sets up the application registry with the
+ registrations your application declares in its ``includeme``
+ function.
+ """
+ self.config = testing.setUp()
+ self.config.include('myproject')
+
+ def tearDown(self):
+ """ Clear out the application registry """
+ testing.tearDown()
+
+ def test_my_view(self):
+ from myproject.views import my_view
+ request = testing.DummyRequest()
+ result = my_view(request)
+ self.assertEqual(result.status, '200 OK')
+ body = result.app_iter[0]
+ self.assertTrue('Welcome to' in body)
+ self.assertEqual(len(result.headerlist), 2)
+ self.assertEqual(result.headerlist[0],
+ ('Content-Type', 'text/html; charset=UTF-8'))
+ self.assertEqual(result.headerlist[1], ('Content-Length',
+ str(len(body))))
+
+class FunctionalTests(unittest.TestCase):
+ def setUp(self):
+ from myproject import main
+ app = main({})
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+
+ def test_root(self):
+ res = self.testapp.get('/', status=200)
+ self.assertTrue('Pyramid' in res.body)
diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py
index 8c019af51..9f34540a7 100644
--- a/docs/narr/MyProject/setup.py
+++ b/docs/narr/MyProject/setup.py
@@ -1,30 +1,42 @@
-import os
+"""Setup for the MyProject package.
+"""
+import os
from setuptools import setup, find_packages
-here = os.path.abspath(os.path.dirname(__file__))
-with open(os.path.join(here, 'README.txt')) as f:
- README = f.read()
-with open(os.path.join(here, 'CHANGES.txt')) as f:
- CHANGES = f.read()
-requires = [
+HERE = os.path.abspath(os.path.dirname(__file__))
+
+
+with open(os.path.join(HERE, 'README.txt')) as fp:
+ README = fp.read()
+
+
+with open(os.path.join(HERE, 'CHANGES.txt')) as fp:
+ CHANGES = fp.read()
+
+
+REQUIRES = [
'pyramid',
'pyramid_chameleon',
'pyramid_debugtoolbar',
'waitress',
]
+TESTS_REQUIRE = [
+ 'webtest'
+ ]
+
setup(name='MyProject',
version='0.0',
description='MyProject',
long_description=README + '\n\n' + CHANGES,
classifiers=[
- "Programming Language :: Python",
- "Framework :: Pyramid",
- "Topic :: Internet :: WWW/HTTP",
- "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
- ],
+ 'Programming Language :: Python',
+ 'Framework :: Pyramid',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
+ ],
author='',
author_email='',
url='',
@@ -32,11 +44,10 @@ setup(name='MyProject',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
- install_requires=requires,
- tests_require=requires,
- test_suite="myproject",
+ install_requires=REQUIRES,
+ tests_require=TESTS_REQUIRE,
+ test_suite='myproject',
entry_points="""\
[paste.app_factory]
main = myproject:main
- """,
- )
+ """)
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index e001ad81c..ecda57489 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -128,8 +128,9 @@ functions accepts various arguments that influence the environment of the
test. See the :ref:`testing_module` API for information about the extra
arguments supported by these functions.
-If you also want to make :func:`~pyramid.threadlocal.get_current_request` return something
-other than ``None`` during the course of a single test, you can pass a
+If you also want to make :func:`~pyramid.threadlocal.get_current_request`
+return something other than ``None`` during the course of a single test, you
+can pass a
:term:`request` object into the :func:`pyramid.testing.setUp` within the
``setUp`` method of your test:
@@ -333,66 +334,49 @@ Creating Integration Tests
--------------------------
In :app:`Pyramid`, a *unit test* typically relies on "mock" or "dummy"
-implementations to give the code under test only enough context to run.
+implementations to give the code under test enough context to run.
"Integration testing" implies another sort of testing. In the context of a
-:app:`Pyramid` integration test, the test logic tests the functionality of
-some code *and* its integration with the rest of the :app:`Pyramid`
+:app:`Pyramid` integration test, the test logic exercises the functionality of
+the code under test *and* its integration with the rest of the :app:`Pyramid`
framework.
-In :app:`Pyramid` applications that are plugins to Pyramid, you can create an
-integration test by including its ``includeme`` function via
-:meth:`pyramid.config.Configurator.include` in the test's setup code. This
-causes the entire :app:`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 :app:`Pyramid`.
+Creating an integration test for a :app:`Pyramid` application usually means
+invoking the application's ``includeme`` function via
+:meth:`pyramid.config.Configurator.include` within the test's setup code. This
+causes the entire :app:`Pyramid` environment to be set up, simulating what
+happens when your application is run "for real". This is a heavy-hammer way of
+making sure that your tests have enough context to run properly, and tests your
+code's integration with the rest of :app:`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``, and that
-there is a ``views`` module in the app with a function with the name
-``my_view`` in it that returns the response 'Welcome to this application'
-after accessing some values that require a fully set up environment.
+.. seealso::
-.. code-block:: python
- :linenos:
+ See also :ref:`including_configuration`
- import unittest
+Let's demonstrate this by showing an integration test for a view.
- from pyramid import testing
+Given the following view definition, which assumes that your application's
+:term:`package` name is ``myproject``, and within that :term:`package` there
+exists a module ``views``, which in turn contains a :term:`view` function named
+``my_view``:
- class ViewIntegrationTests(unittest.TestCase):
- def setUp(self):
- """ This sets up the application registry with the
- registrations your application declares in its ``includeme``
- function.
- """
- import myapp
- self.config = testing.setUp()
- self.config.include('myapp')
+ .. literalinclude:: MyProject/myproject/views.py
+ :linenos:
+ :lines: 1-6
+ :language: python
- def tearDown(self):
- """ Clear out the application registry """
- testing.tearDown()
+You'd then create a ``tests`` module within your ``myproject`` package,
+containing the following test code:
- def test_my_view(self):
- from myapp.views import my_view
- request = testing.DummyRequest()
- result = my_view(request)
- self.assertEqual(result.status, '200 OK')
- body = result.app_iter[0]
- self.assertTrue('Welcome to' in body)
- self.assertEqual(len(result.headerlist), 2)
- self.assertEqual(result.headerlist[0],
- ('Content-Type', 'text/html; charset=UTF-8'))
- self.assertEqual(result.headerlist[1], ('Content-Length',
- str(len(body))))
-
-Unless you cannot avoid it, you should prefer writing unit tests that use the
-:class:`~pyramid.config.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 about.
+ .. literalinclude:: MyProject/myproject/tests.py
+ :linenos:
+ :pyobject: ViewIntegrationTests
+ :language: python
+
+Writing unit tests that use the :class:`~pyramid.config.Configurator` API to
+set up the right "mock" registrations is often preferred to creating
+integration tests. Unit tests will run faster (because they do less for each
+test) and are usually easier to reason about.
.. index::
single: functional tests
@@ -404,34 +388,40 @@ Creating Functional Tests
Functional tests test your literal application.
-The below test assumes that your application's package name is ``myapp``, and
-that there is a view that returns an HTML body when the root URL is invoked.
-It further assumes that you've added a ``tests_require`` dependency on the
-``WebTest`` package within your ``setup.py`` file. :term:`WebTest` is a
-functional testing package written by Ian Bicking.
+In Pyramid, functional tests are typically written using the :term:`WebTest`
+package, which provides APIs for invoking HTTP(S) requests to your application.
-.. code-block:: python
- :linenos:
+Regardless of which testing :term:`package` you use, ensure to add a
+``tests_require`` dependency on that package to to your application's
+``setup.py`` file:
- import unittest
+ .. literalinclude:: MyProject/setup.py
+ :linenos:
+ :emphasize-lines: 26-28,48
+ :language: python
- class FunctionalTests(unittest.TestCase):
- def setUp(self):
- from myapp import main
- app = main({})
- from webtest import TestApp
- self.testapp = TestApp(app)
-
- def test_root(self):
- res = self.testapp.get('/', status=200)
- self.assertTrue('Pyramid' in res.body)
-
-When this test is run, each test creates a "real" WSGI application using the
-``main`` function in your ``myapp.__init__`` module and uses :term:`WebTest`
-to wrap that WSGI application. It assigns the result to ``self.testapp``.
-In the test named ``test_root``, we use the testapp's ``get`` method to
-invoke the root URL. We then assert that the returned HTML has the string
-``Pyramid`` in it.
+Assuming your :term:`package` is named ``myproject``, which contains a
+``views`` module, which in turn contains a :term:`view` function ``my_view``
+that returns a HTML body when the root URL is invoked:
+
+ .. literalinclude:: MyProject/myproject/views.py
+ :linenos:
+ :language: python
+
+Then the following example functional test (shown below) demonstrates invoking
+the :term:`view` shown above:
+
+ .. literalinclude:: MyProject/myproject/tests.py
+ :linenos:
+ :pyobject: FunctionalTests
+ :language: python
+
+When this test is run, each test method creates a "real" :term:`WSGI`
+application using the ``main`` function in your ``myproject.__init__`` module,
+using :term:`WebTest` to wrap that WSGI application. It assigns the result to
+``self.testapp``. In the test named ``test_root``. The ``TestApp``'s ``get``
+method is used to invoke the root URL. Finally, an assertion is made that the
+returned HTML contains the text ``MyProject``.
See the :term:`WebTest` documentation for further information about the
methods available to a :class:`webtest.app.TestApp` instance.