After setting up a basic Django CI for standard unit tests in my last post, I now also wanted to add functional UI tests with Selenium to my testing procedure. That’s why in this post I want to cover how to setup a headless functional test environment for Django projects on a Debian 7 server. In the end of this post we will also see a simple Django UI test case example.

Installing Firefox on Debian 7

Of course, in a first step we need to install a web browser with which we can run our functional tests. I decided to use Firefox. Since Debian 7 supports Iceweasel, installing Firefox requires a little extra work. One way is to add deb debian import to /etc/apt/source.list and to import the necessary GPG keys. How this can be done is explained here.

Installing Virtual Displays

Most servers do not have a display - so in order to start a browser and run UI tests, in a next step we have to install a virtual display environment. For this purpose we can install xvfb:

$ sudo apt-get install xvfb

xvfb can then be used to start a virtual display in which we can run our browser window.

Now we also need a way to start xvfb from within our test. PyVirtualDisplay is a wrapper for xvfb, which makes it easy for us to create a virtual display inside our python code. It can be simply installed via pip (preferably inside your virtual python environment):

(py-env)$ pip install pyvirtualdisplay

I strongly recommend the use of virtual python environments when working with Django. These can save you from a lot of trouble in case you are having multiple projects on the same server - especially when upgrades and migrations are coming closer!

At the end of this post I show a test case in which a virtual display with the help of PyVirtualDisplay is created.

Installing Selenium

I’ve had very good experiences with Selenium in the past. It has a great community and quick fixes for new browser versions. Lucky for us, Selenium also comes for Python and can be installed via pip:

(py-env)$ pip install selenium

An Example Test

Now that we have everything installed/setup, lets take a look at a very basic “Hello World!” example test case for a basic html test website, which is returned when calling /test/example on our Django server.

We first create a virtual display with dimension 1024x786. Next, we use the Selenium Firefox webdriver and open our test website. After this, we try to fetch the element with the id test, retrieve its text and verify that it is indeed “Hello World!”. When the test finishes, we tear down the browser and the virtual display. Yep, it’s that easy!

I use Django’s @skipIf tag in order to easily disable functional UI tests. As we could see, functional UI tests require extra packages and a specific browser. In case you only want to test those on the CI server you have to set inside the CI’s project’s SKIP_FUNCTIONAL_TESTS = False. The Developer’s client on the other hand could easily disable the functional tests by not setting SKIP_FUNCTIONAL_TESTS at all in his local project’s Thus, on a local dev client one could easily exclude functional tests and only perform unit tests.

That’s it! We are now able to easily write UI tests. For embedding your tests in a CI process, please refer to my previous post on how to setup a Django CI with Git and Jenkins.

Happy UI testing!