Provide unit testing for our project's Python code.
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 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.
First we copy the results of the previous step, as well as install the nose package:
$ 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import unittest from pyramid import testing class TutorialViewTests(unittest.TestCase): def setUp(self): self.config = testing.setUp() def tearDown(self): testing.tearDown() def test_hello_world(self): from tutorial import hello_world request = testing.DummyRequest() response = hello_world(request) self.assertEqual(response.status_code, 200)
Now run the tests:
$ $VENV/bin/nosetests tutorial . ---------------------------------------------------------------------- Ran 1 test in 0.141s OK
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.TutorialViewTests.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.