Steve Piercy
2017-05-12 396c5a116982626049c66488750de24e2967dc71
commit | author | age
b731b5 1 .. _qtut_unit_testing:
PE 2
86e187 3 =============================
SP 4 05: Unit Tests and ``pytest``
5 =============================
b1b922 6
PE 7 Provide unit testing for our project's Python code.
86e187 8
b1b922 9
PE 10 Background
11 ==========
12
86e187 13 As the mantra says, "Untested code is broken code." The Python community has
SP 14 had a long culture of writing test scripts which ensure that your code works
15 correctly as you write it and maintain it in the future. Pyramid has always had
16 a deep commitment to testing, with 100% test coverage from the earliest
17 pre-releases.
b1b922 18
86e187 19 Python includes a :ref:`unit testing framework
SP 20 <python:unittest-minimal-example>` in its standard library. Over the years a
21 number of Python projects, such as :ref:`pytest <pytest:features>`, have
22 extended this framework with alternative test runners that provide more
23 convenience and functionality. The Pyramid developers use ``pytest``, which
24 we'll use in this tutorial.
b1b922 25
86e187 26 Don't worry, this tutorial won't be pedantic about "test-driven development"
SP 27 (TDD). We'll do just enough to ensure that, in each step, we haven't majorly
28 broken the code. As you're writing your code, you might find this more
29 convenient than changing to your browser constantly and clicking reload.
b1b922 30
86e187 31 We'll also leave discussion of `pytest-cov
6312eb 32 <http://pytest-cov.readthedocs.io/en/latest/>`_ for another section.
86e187 33
b1b922 34
PE 35 Objectives
36 ==========
37
86e187 38 - Write unit tests that ensure the quality of our code.
b1b922 39
86e187 40 - Install a Python package (``pytest``) which helps in our testing.
SP 41
b1b922 42
PE 43 Steps
44 =====
45
86e187 46 #. First we copy the results of the previous step, as well as install the
SP 47    ``pytest`` package:
b1b922 48
PE 49    .. code-block:: bash
50
187104 51     $ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing
d68cbc 52     $ $VENV/bin/pip install -e .
86e187 53     $ $VENV/bin/pip install pytest
b1b922 54
PE 55 #. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``:
56
57    .. literalinclude:: unit_testing/tutorial/tests.py
58     :linenos:
59
60 #. Now run the tests:
61
62    .. code-block:: bash
63
64
86e187 65     $ $VENV/bin/py.test tutorial/tests.py -q
b1b922 66     .
86e187 67     1 passed in 0.14 seconds
b1b922 68
PE 69
70 Analysis
71 ========
72
86e187 73 Our ``tests.py`` imports the Python standard unit testing framework. To make
SP 74 writing Pyramid-oriented tests more convenient, Pyramid supplies some
75 ``pyramid.testing`` helpers which we use in the test setup and teardown. Our
76 one test imports the view, makes a dummy request, and sees if the view returns
77 what we expect.
b1b922 78
86e187 79 The ``tests.TutorialViewTests.test_hello_world`` test is a small example of a
SP 80 unit test. First, we import the view inside each test. Why not import at the
81 top, like in normal Python code? Because imports can cause effects that break a
82 test. We'd like our tests to be in *units*, hence the name *unit* testing. Each
83 test should isolate itself to the correct degree.
b1b922 84
86e187 85 Our test then makes a fake incoming web request, then calls our Pyramid view.
SP 86 We test the HTTP status code on the response to make sure it matches our
87 expectations.
b1b922 88
PE 89 Note that our use of ``pyramid.testing.setUp()`` and
90 ``pyramid.testing.tearDown()`` aren't actually necessary here; they are only
91 necessary when your test needs to make use of the ``config`` object (it's a
92 Configurator) to add stuff to the configuration state before calling the view.
93
86e187 94
65687f 95 Extra credit
b1b922 96 ============
PE 97
86e187 98 #. Change the test to assert that the response status code should be ``404``
SP 99    (meaning, not found). Run ``py.test`` again. Read the error report and see
100    if you can decipher what it is telling you.
b1b922 101
86e187 102 #. As a more realistic example, put the ``tests.py`` back as you found it, and
SP 103    put an error in your view, such as a reference to a non-existing variable.
104    Run the tests and see how this is more convenient than reloading your
105    browser and going back to your code.
b1b922 106
PE 107 #. Finally, for the most realistic test, read about Pyramid ``Response``
86e187 108    objects and see how to change the response code. Run the tests and see how
SP 109    testing confirms the "contract" that your code claims to support.
b1b922 110
PE 111 #. How could we add a unit test assertion to test the HTML value of the
112    response body?
113
114 #. Why do we import the ``hello_world`` view function *inside* the
115    ``test_hello_world`` method instead of at the top of the module?
116
2033ee 117 .. seealso:: See also :ref:`testing_chapter`