summaryrefslogtreecommitdiff
path: root/docs/quick_tutorial/unit_testing.rst
diff options
context:
space:
mode:
authorPaul Everitt <paul@agendaless.com>2013-09-13 16:52:14 -0400
committerPaul Everitt <paul@agendaless.com>2013-09-13 16:52:14 -0400
commitb1b92284f496800a4dfd2cea72cb9be07ba8661c (patch)
tree9dfa72427fd6aa0a3a7aaba72be4a4e49380ee26 /docs/quick_tutorial/unit_testing.rst
parent1d04f8f0b483b8d595f5ada24ae5108affe80160 (diff)
downloadpyramid-b1b92284f496800a4dfd2cea72cb9be07ba8661c.tar.gz
pyramid-b1b92284f496800a4dfd2cea72cb9be07ba8661c.tar.bz2
pyramid-b1b92284f496800a4dfd2cea72cb9be07ba8661c.zip
First cut at import of quick tutorial.
Diffstat (limited to 'docs/quick_tutorial/unit_testing.rst')
-rw-r--r--docs/quick_tutorial/unit_testing.rst117
1 files changed, 117 insertions, 0 deletions
diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst
new file mode 100644
index 000000000..cc9dfcc8a
--- /dev/null
+++ b/docs/quick_tutorial/unit_testing.rst
@@ -0,0 +1,117 @@
+===========================
+05: Unit Tests and ``nose``
+===========================
+
+Provide unit testing for our project's Python code.
+
+Background
+==========
+
+As the mantra says, "Untested code is broken code." The Python
+community has had a long culture of writing test scripts which ensure
+that your code works correctly as you write it and maintain it in the
+future. Pyramid has always had a deep commitment to testing,
+with 100% test coverage from the earliest pre-releases.
+
+Python includes a
+:ref:`unit testing framework <python:unittest-minimal-example>` in its
+standard library. Over the years a number of Python projects, such as
+`nose <https://pypi.python.org/pypi/nose/>`_, have extended this
+framework with alternative test runners that provide more convenience
+and functionality. The Pyramid developers use ``nose``, which we'll thus
+use in this tutorial.
+
+Don't worry, this tutorial won't be pedantic about "test-driven
+development" (TDD.) We'll do just enough to ensure that, in each step,
+we haven't majorly broken the code. As you're writing your code you
+might find this more convenient than changing to your browser
+constantly and clicking reload.
+
+We'll also leave discussion of
+`coverage <https://pypi.python.org/pypi/coverage>`_ for another section.
+
+Objectives
+==========
+
+- Write unit tests that ensure the quality of our code
+
+- Install a Python package (``nose``) which helps in our testing
+
+Steps
+=====
+
+#. First we copy the results of the previous step, as well as install
+ the ``nose`` package:
+
+ .. code-block:: bash
+
+ (env27)$ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing
+ (env27)$ python setup.py develop
+ (env27)$ easy_install nose
+
+#. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``:
+
+ .. literalinclude:: unit_testing/tutorial/tests.py
+ :linenos:
+
+#. Now run the tests:
+
+ .. code-block:: bash
+
+
+ (env27)$ nosetests tutorial
+ .
+ ----------------------------------------------------------------------
+ Ran 1 test in 0.141s
+
+ OK
+
+Analysis
+========
+
+Our ``tests.py`` imports the Python standard unit testing framework. To
+make writing Pyramid-oriented tests more convenient, Pyramid supplies
+some ``pyramid.testing`` helpers which we use in the test setup and
+teardown. Our one test imports the view, makes a dummy request, and sees
+if the view returns what we expected.
+
+The ``tests.HelloWorldViewTests.test_hello_world`` test is a small
+example of a unit test. First, we import the view inside each test. Why
+not import at the top, like in normal Python code? Because imports can
+cause effects that break a test. We'd like our tests to be in *units*,
+hence the name *unit* testing. Each test should isolate itself to the
+correct degree.
+
+Our test then makes a fake incoming web request, then calls our Pyramid
+view. We test the HTTP status code on the response to make sure it
+matches our expectations.
+
+Note that our use of ``pyramid.testing.setUp()`` and
+``pyramid.testing.tearDown()`` aren't actually necessary here; they are only
+necessary when your test needs to make use of the ``config`` object (it's a
+Configurator) to add stuff to the configuration state before calling the view.
+
+Extra Credit
+============
+
+#. Change the test to assert that the response status code should be
+ ``404`` (meaning, not found.) Run ``nosetests`` again. Read the
+ error report and see if you can decipher what it is telling you.
+
+#. As a more realistic example, put the ``tests.py`` back as you found
+ it and put an error in your view, such as a reference to a
+ non-existing variable. Run the tests and see how this is more
+ convenient than reloading your browser and going back to your code.
+
+#. Finally, for the most realistic test, read about Pyramid ``Response``
+ objects and see how to change the response code. Run the tests and
+ see how testing confirms the "contract" that your code claims to
+ support.
+
+#. How could we add a unit test assertion to test the HTML value of the
+ response body?
+
+#. Why do we import the ``hello_world`` view function *inside* the
+ ``test_hello_world`` method instead of at the top of the module?
+
+.. seealso:: See Also: :ref:`pyramid:testing_chapter`