Django Testing Gotchas

by on December 24, 2008 at 8:04 pm

I don’t think many Django users take advantage of the testing framework. If they had, I’d expect that there would be far more discussions of the edge cases that you hit when you utilize it. I’ve collected a few gotchas that we’ve run into that were non-obvious (to us) and probably will catch other new python programmers.

  • CSRF middleware breaks the TestClient. It doesn’t actually break the TestClient, but it prevents you from easily writing tests that post forms. There currently is a ticket that might fix this.
  • Unicode characters in Doctest strings cause them to fail silently (the doctests are never run). This is actually a problem in the core doctest code from python. Basically, if you have unicode characters in your doctest you need to make the doctest string a raw string (preceding it with the r character).
  • Django does not flush the test db after running unittests. It does flushe and reload the db before every unittest, but not before doctests. Obviously this isn’t a problem if you only use Unit Tests, however you may run into issues if you write doctests that expect an empty db. Don’t program by coincidence and instead flush the db from within a doctest (if needed):
# Clear the DB
>>> from django.core.management import call_command
>>> call_command('flush', verbosity=0, interactive=False)
  • Django TestClient does not play nicely with the PREPEND_WWW setting. If your site uses PREPEND_WWW, you will be unable to use the test client to test if a page loads. That is because PREPEND_WWW causes a 301 redirect to be issued for all TestClient responses. The TestClient is never able to actually load a page (or fail trying). If ticket 4476 is ever integrated, this should solve this problem but in reality developers should handle this at the webserver.
  • Imports in other modules can cause some doctests to fail silently (the doctests are never run). I’ve been a bit sloppy with my module imports - I’ve used project.app.models in some places and app.models in other. I invested time in cleaning up the imports but was never able to get it all to work. I ended up monkeypatching line 895 in django/test/_doctest.py from (yes, consistent imports are a far better solution):
 return module.__name == object.__module__ 

to:

 return module.__name__.find(object.__module__) >=0 
  • Imports in other Modules can result in duplicate signal handlers. Similar to the problem above: These two imports project.app.models and app.models result in modules in different namespaces. If a listener is created on such a module, you end up with two listeners. So when you send a signal, two listeners respond and two actions are taken. This problem never surfaced in production even while tests were having issues so it seemed to be directly related to the test environment.

I’ll add items as I run into them.

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. | Dave Naffziger's BlogDave & Iva Naffziger