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 currentDJANGO_SETTINGS_MODULE
to point to a in-memorysqlite
database, installs a specified set of models into that virgin database and changes theMEDIA_ROOT
to point to a folder in/tmp/
. - A
testenv_teardown
method which cleans up the temporaryMEDIA_ROOT
. - A unit test base class (derived from
unittest.TestCase
) that usestestenv_setup
andtestenv_teardown
. - A new handler,
TestHandler
, derived fromWSGIHandler
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.