Honza Král: testing Django applications

Tags: django, djangocon

Testing is something everyone already does when checking things in the browser or trying it out on the command line. And checking the database contents. Repetitive boring work, so let’s automate it. Let the computer do the boring stuff.

Even if you’re a perfect programmer, tests will make you fearless of deployment, refactoring (“what will I break”), new developers (“can I trust them”) and so on.

There are various tests you can do. Integration tests, unit tests, performance tests, etc. Unit testing is the lowest level. Don’t confuse unit testing with python’s unittest module, as that’s just a test mechanism that you can use for various types of tests.

If you do unit testing, you should only test one single thing at a time. Unit tests should be FAST. Don’t depend on external components: isolation and speed. Don’t touch the database.

Integration tests test the integration of (preferably already-unittested) code with external components and with other code blocks. So do touch your database this time. Integration tests are the most common tests in Django apps. The disadvantage: they’re slower and they cover more code.

Each piece of code should do just one thing: no side effects. This really helps testability. request is bad in the sense that it contains a lot of data, potentially. So don’t pass the request on to other functions, but only the items that are needed.

Regarding views: class based views are great for testing. The class’s __call__(self, request) method is the one that’s called by the view mechanism. The various calculations are done by the other methods in the class, which only get the parameters that they need, making them better testable. (You can also have a view method that farms out its work to other helper methods instead of a class, but the principle is the same.

Template tags also help in separating components for easy testability. You can easily put a small template that only loads and renders one templatetag in your test setup and test the template tag completely.

Fixtures only work well for static data. Using a factory is often easier. A factory creates a new object with some defaults, but it allows you to override any one of the defaults. Just build one yourself.

Testing forms is easy by providing a data dictionary with correct form data. Test that it works. Then change individual fields of the correct data and check that it breaks.

Continuous integration (“buildbot” or “hudson”) help in always running the tests and warning everyone once the tests break. Don’t let your test suite break: once broken, it is easy to keep on adding functionality without tests or with broken tests.

When tests fail you must know what went wrong. For that reason, he doesn’t use doctests…

If you code, at least start with at least a trivial test as a starting point.

Some happy benefits of testing right:

  • No temporary test scripts/junk/whatever lying around. You have a clean way to test everything.

  • You have a convenient way of bootstrapping your applications. Creating the initial data and so.

  • Calmer nerves.

Question: what’s missing from django’s test infrastructure? Apart from handier form support? Answer: code generators that also add a testcase when adding a model or some script that you can call after you’ve added a model yourself.

Spree river
vanrees.org logo

About me

My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.

Weblog feeds

Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):