From b1b92284f496800a4dfd2cea72cb9be07ba8661c Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Fri, 13 Sep 2013 16:52:14 -0400 Subject: First cut at import of quick tutorial. --- docs/quick_tutorial/unit_testing.rst | 117 +++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 docs/quick_tutorial/unit_testing.rst (limited to 'docs/quick_tutorial/unit_testing.rst') 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 ` in its +standard library. Over the years a number of Python projects, such as +`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 `_ 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` -- cgit v1.2.3 From 4042c772c8043ac96a22db439a736fec9ea2aafa Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Fri, 13 Sep 2013 17:09:35 -0400 Subject: All the references re-wired. --- docs/quick_tutorial/unit_testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial/unit_testing.rst') diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index cc9dfcc8a..566e09252 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -114,4 +114,4 @@ Extra Credit #. 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` +.. seealso:: See Also: :ref:`testing_chapter` -- cgit v1.2.3 From 0a784868bdbc3a0eb226ed00e8d89cda9d181ec5 Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Fri, 13 Sep 2013 17:11:42 -0400 Subject: Fix naming of virtualenv prefix. --- docs/quick_tutorial/unit_testing.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial/unit_testing.rst') diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index 566e09252..e87c5af62 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -45,9 +45,9 @@ Steps .. code-block:: bash - (env27)$ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing - (env27)$ python setup.py develop - (env27)$ easy_install nose + (env)$ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing + (env)$ python setup.py develop + (env)$ easy_install nose #. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``: @@ -59,7 +59,7 @@ Steps .. code-block:: bash - (env27)$ nosetests tutorial + (env)$ nosetests tutorial . ---------------------------------------------------------------------- Ran 1 test in 0.141s -- cgit v1.2.3 From b0b28ede912c817a62a84b97c332e39eda02d166 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Mon, 16 Sep 2013 02:14:53 +0200 Subject: s/env/venv just for sake of consistency --- docs/quick_tutorial/unit_testing.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial/unit_testing.rst') diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index e87c5af62..de30ea436 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -45,9 +45,9 @@ Steps .. code-block:: bash - (env)$ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing - (env)$ python setup.py develop - (env)$ easy_install nose + (venv)$ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing + (venv)$ python setup.py develop + (venv)$ easy_install nose #. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``: @@ -59,7 +59,7 @@ Steps .. code-block:: bash - (env)$ nosetests tutorial + (venv)$ nosetests tutorial . ---------------------------------------------------------------------- Ran 1 test in 0.141s -- cgit v1.2.3