Selenium’s been around for a long time now, and is available in various programming languages, but up until Django 1.4 came along you couldn’t have your Selenium tests (easily) integrated with your Django test suite. Since then, a new class named LiveServerTestCase, that your Selenium test classes can inherit from, was introduced. This class will automatically run a test server in the background and your Selenium tests will be run against that server. It not only simplifies the process, but it also means your tests can be setup the same way your Django tests are, and so both can be run together without any aditional setup using the standard manage.py test
The best way to “understand” Selenium is by actually seeing it in action, so we prepared an example project with a small test for the Django Admin login page. To play with it, just create a new virtualenv and checkout our sample project on Github. The only dependencies are Django and Selenium, so a simple pip install -r selenium_intro/requirements.pip
inside your virtualenv will be enough.
To make things simple, we’ll use Firefox by default since it has webdriver support built-in. If you want to run tests on Chrome you’ll need to download the chrome driver separately from chromedriver downloads and add a SELENIUM_WEBDRIVER
variable in settings.py
to point to the Chrome driver instead (see selenium_tests.webdriver
in the sample project).
configuration serves two purposes:
Not everyone is forced to run the Selenium tests, so it’s opt-in through INSTALLED_APPS
You can switch to another webdriver without a big hassle. For production tests you can write a separate command and change the driver on the fly so you can test different browsers.
App / Test Structure
Selenium tests can be setup inside each app’s test directory just like a regular test would be, but since they’re very tied to the specific project, our preference is to create an app where all the tests are stored. We called this “selenium_tests” and other than the tests themselves, there are two other files:
Here we defined our base test class and helper methods. We have an “open” helper because Selenium needs an absolute URL (including server and port), but you can also define methods for common operations like “sign in”, “sign out”, etc.. that you may need throughout all the tests.
Because the default webdriver query methods are very verbose (hello Java!) and missing some important features, we felt the need to create a custom webdriver class so we can add some functionality of our own.
Another option is to use splinter, which provides a much nicer Python interface to Selenium.
In this example, we have only one method, which is very handy:
is basically a shortcut for both “find_elements_by_css_selector” and “find_element_by_css_selector”, and as the method names imply, it enables you to find DOM elements using regular CSS selectors.wait_for_css
to add “generic” shortcuts and test.py
for “app specific” shortcuts (like sign in).
Writing your first test
Our example test will be a very simple Django admin sign in test, here’s how our tests/auth.py
looks like, and the inline documentation should be enough to get an understanding of how it works: