Unit-testing – What and how to unit test a django web application

djangounit testing

I am writing unit tests for a web frontend implemented in Django.
I have written unit tests that check that all views return the correct status code (200, 302 etc) so that template errors (which give 500) are found. I also do HTML validation with tidylib.

What else is there I should (or can) do?

Models are unit tested elsewhere, forms have dependencies (namely on models) so is there way to unit test them – in general case there is something one can do, but what can I do (without a huge effort) leveraging the Django/python unit test framework?

Best Answer

If you look at the Model-Template-View triads, each distinct component and any intermediary component in between can be tested separately. Say you have a Foo model and need to add controllers for CRUD behavior in a simple and straightforward manner:

  1. You unit test the Foo model to assert that the business logic is implemented.
  2. You unit test FooForm to assert form.is_valid() is returning expected results for the inputs your tests supply directly.
  3. You only need to assert that the class-based CRUD views are working with the Foo model and FooForm respectively.

In general, there's no extensive frontend testing happening in Django projects, especially those that utilize class-based views and unit test the views directly, you won't see any assertContains/assertNotContains tests at all, although the LiveServerTestCase is going to change that a bit, at least when it comes to asserting behavior for project's that aren't already writing JavaScript tests in one of the testing frameworks.

It's as if you have your backend hat on when your writing unit tests. If you want to add a success message to the CUD views, you'd assert that a success-level message has been added to the list of user's messages after a successful request, but you won't care whether that message is a part of the response or not. Similarly, we test that the context is populated with the correct Foo objects for a request, but we don't care if and how they're displayed.

And this is where Lettuce comes into play, especially if you want to test your application's behavior from a user's perspective. It's appropriate to work with the content of a response object and to ignore the underlying implementations that produced the response. Here you won't care whether or not there is a success-level message associated with a user, you'll just want to make sure it's there in the response and you won't care whether the appropriate Foo objects are in the context, you'll want to assert that their content is present in the response.

Related Topic