Testing Django apps

I’ve started work on a new, quite large Django project. It will be six weeks until I’ve implemented everything in the specification, so I wanted to get in early with some tests.

Building on the code and ideas of Hugo, Ian Maurer and Sune Kirkeby, I created a simple Python module that provides:

  • A testenv_setup method that modifies the database settings in the current DJANGO_SETTINGS_MODULE to point to a in-memory sqlite database, installs a specified set of models into that virgin database and changes the MEDIA_ROOT to point to a folder in /tmp/.
  • A testenv_teardown method which cleans up the temporary MEDIA_ROOT.
  • A unit test base class (derived from unittest.TestCase) that uses testenv_setup and testenv_teardown.
  • A new handler, TestHandler, derived from WSGIHandler which allows the user to construct requests to the Django processing framework very easily (e.g. get_response("/my/url/")) and returns the original objects created for the response and allows exceptions to bubble rather than just pushing back the HTML only. This facilitates easy test writing. Of course the HTML is there too, and, like Sune Kirkeby, I push it into a BeautifulSoup object for handy parsing.

The result is a simple module that can be used to create either doctests and unit tests that test both models and views. I prefer doctests, because they just seem more pythonic to me. Unit tests are great, but there’s a weighty Javaness to them, they’re more clunky to write, which is critical. Doctests are also a better fit for Django’s model magic. Because of the DB settings monkey-patching, unit tests must import the models after setUp, within each test function. This just adds tonnes of lines of cruft. With doctests, I just have a block of imports at the top of each test docstring.