Selenium Tests in Django & Docker
Update: This post has been revised and updated.
Read: Testing Django with Selenium, pytest, and Docker (2023)
Original post
Running Selenium tests in Django using Docker is an easy, convenient and
repeatable strategy to run UI tests across multiple development and testing
environments. It requires some light customization of the
StaticLiveServerTestCase
class, but once configured, the Selenium UI tests
will seamlessly integrate into your existing test suite and dockerized CI
build.
SeleniumHQ provides Docker images for Chrome and Firefox -- if these browsers are sufficient for your UI testing needs, great! You can test against real browsers and avoid the cost of a third-party service subscription.
If you are already familiar with Selenium tests in Django, the setup is very similar with the exception of a few caveats:
- Use the selenium
Remote
web driver to connect to the Docker container - The
ALLOWED_HOSTS
setting is enforced duringLiveServerTestCase
- The Django test server must bind to
0.0.0.0
in order to allow the selenium docker container to connect.
How-To
For the full example, check out the example app:
https://github.com/marcgibbons/django-selenium-docker
The app uses docker-compose to link the Docker containers.
docker-compose.yml
Under services
, define a container called selenium
. In this example, we'll
use the standalone-chrome-debug
container which gives us the ability to
connect remotely using VNC Viewer. This means we can gain
access to the GUI to debug, inspect the DOM, use the JS console, etc.
selenium:
image: selenium/standalone-chrome-debug:3.7.1
ports:
- 4444:4444 # Selenium
- 5900:5900 # VNC server
Make sure you add a link to this container from the Django container:
django:
...
links:
- selenium
...
tests.py
The following is a slightly modified version of the example provided in the Django LiveServerTestCase documentation. Use this base class for all your Selenium test cases.
import socket
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test import override_settings, tag
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
@override_settings(ALLOWED_HOSTS=['*']) # Disable ALLOW_HOSTS
class BaseTestCase(StaticLiveServerTestCase):
"""
Provides base test class which connects to the Docker
container running Selenium.
"""
host = '0.0.0.0' # Bind to 0.0.0.0 to allow external access
@classmethod
def setUpClass(cls):
super().setUpClass()
# Set host to externally accessible web server address
cls.host = socket.gethostbyname(socket.gethostname())
# Instantiate the remote WebDriver
cls.selenium = webdriver.Remote(
# Set to: htttp://{selenium-container-name}:port/wd/hub
# In our example, the container is named `selenium`
# and runs on port 4444
command_executor='http://selenium:4444/wd/hub',
# Set to CHROME since we are using the Chrome container
desired_capabilities=DesiredCapabilities.CHROME,
)
cls.selenium.implicitly_wait(5)
@classmethod
def tearDownClass(cls):
cls.selenium.quit()
super().tearDownClass()
Connecting with VNC Viewer
This is the cool part. The SeleniumHQ containers with the -debug
suffix
run a VNC server to which we can connect from the host (i.e. remote desktop.)
The setup is very easy.
- First, download and install VNC Viewer.
- Create a new connection to
0.0.0.0:5900
- Start the selenium container (
docker-compose start selenium
) - Connect to container from VNC. The password is
secret
. - Run the test suite and watch the browser spin up!
Debugging
Now that you have a remote connection established to the container, you can
insert a breakpoint in your code (pdb
) and have the ability to control
the browser, use the console, etc. Awesome!
Enjoy!
Credits
The Django TestCase configuration was pieced together from this StackOverflow article.