Sunday 31 March 2013

Django-webtest

When testing my views in a Django application, I always use django-webtest. This is a Django binding for a library from paste, which simply talks to a web application using wsgi, and acts like a browser in a very basic manner.

For example: submitting forms works as expected and sends the data contained in the inputs inside such form, in the method defined in <form method=""> and to the url defined in <form action="">, click()ing links takes you to the url in their href attribute, etc.

These are tests which will actually tell you if your templates are broken. So you are not simply testing your views. You are testing the template html as well. If you forget to add that {÷ csrf_token ÷} to your form, the test will fail. If one of the designers accidentally removes your "edit profile" link, you will know that.

An obviously missing feature is JavaScript support. So, if your app doesn't work without it, you won't be able to use this to the fullest.

Your view testing code with WebTest will look like this:

    def test_delete_object(self):
        object = construct_model_instance_somehow()
        owner = object.owner

        # go to the object's page, logged in as the owner
        details_page = self.app.get(object.get_absolute_url(), user=owner)

        # click delete link
        delete_page = details_page.click('delete')

        form = delete_page.form

        form.submit().follow()

        self.assertFalse(Object.objects.filter(
            some_data='you know').exists())

Every .click() call is an assertion that the page loads with no errors, and returns the response. You can actually chain click calls, even though I don't find it so useful myself. If you want a BeautifulSoup to check that your HTML response contains the correct links, just install BeautifulSoup (3.x for now) in your environment and access response.html to get a soup. Not to mention .showbrowser(), which fires up your browser to show you the HTML directly. A huge time saver for debugging.

In conclusion, very useful stuff. You should use it.

2 comments:

  1. Hi, could you please point me to the basics of using WebTest - eg. where in the project do my files need to be ? what should go in the 'environ' and 'start_response' params ? etc.
    -Aash

    ReplyDelete
  2. It has been a bit since I used this library.

    You might have seen examples of a wsgi app on a web test doc page, because environ and start_response are arguments to the wsgi callable (see "simplest app" here: http://pythonweb.org/projects/webmodules/doc/0.5.3/html_multipage/lib/example-wsgiSimple.html).

    Basically this is because webtest will talk to your application via wsgi, which is conveniently the same interface your server will (hopefully) use to talk to it.

    If you are on django, django-webtest will take care of plumbing webtest to your app, so you will just have to install it, import it and use it.

    Otherwise, every web framework that I know of has an easy way to get the wsgi application callable, which you can pass to webtest so it can talk to your app.

    Hope this helps!

    ReplyDelete