diff options
| author | Chris McDonough <chrism@plope.com> | 2013-10-02 15:52:22 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2013-10-02 15:52:22 -0400 |
| commit | a2d4c260952a8e2329df0c4a66d7239f2e8d0652 (patch) | |
| tree | fbf3d72d0fdb466735367fc37b7a02333d0b6f09 /docs/quick_tutorial/unit_testing.rst | |
| parent | b117f9c16e8c59915bb3d87d8e548e1111ed6899 (diff) | |
| parent | 66be39bf656a2840931603bc959e38ff95e53164 (diff) | |
| download | pyramid-a2d4c260952a8e2329df0c4a66d7239f2e8d0652.tar.gz pyramid-a2d4c260952a8e2329df0c4a66d7239f2e8d0652.tar.bz2 pyramid-a2d4c260952a8e2329df0c4a66d7239f2e8d0652.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
Diffstat (limited to 'docs/quick_tutorial/unit_testing.rst')
| -rw-r--r-- | docs/quick_tutorial/unit_testing.rst | 119 |
1 files changed, 119 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..73b33c588 --- /dev/null +++ b/docs/quick_tutorial/unit_testing.rst @@ -0,0 +1,119 @@ +.. _qtut_unit_testing: + +=========================== +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 + + $ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing + $ $VENV/bin/python setup.py develop + $ $VENV/bin/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 + + + $ $VENV/bin/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:`testing_chapter` |
