Why
In a recent Django project, I needed to implement end-to-end testing using Selenium. While the setup worked smoothly locally, I wanted to containerize the development environment, including the test suites. However, I encountered a challenge when running the tests in Docker: Selenium requires a browser to be installed in the system, and not all Docker images come with a browser pre-installed.
Problem
version: '3'
services:
# django
app:
build: .
command: python manage.py runserver 0.0.0.0:8080
volumes:
# ...
ports:
- "8080:8080"
# database
db:
# ...
Writing a docker compose file for these services was quite straightforward, everything runs smoothly until I run the test suites. Selenium requires the chosen browser to be pre-installed in your system in order to perform the tests, however, not every docker image comes with a browser.
Solution
So there are two options:
- Modify the Dockerfile of
app
to include the target browser - Use the Selenium official docker image
Whilst the first option can work, it might not be the most reusable and maintainable solution.
So here is the addition to the docker-compose.yaml
file:
services:
# ...
# other services
# ...
# selenium firefox driver
selenium-firefox:
image: selenium/standalone-firefox
shm_size: 2gb
ports:
- "4444:4444"
- "7900:7900"
restart: "no"
The project is using LiveServerTestCase
from the django.test
package that automatically sets up a live development server on a random port, and the tests can make real HTTP requests to this server. Therefore, an important step for the end-to-end testing to work is to modify the host
variable for any class using the LiveServerTestCase
.
from django.test import LiveServerTestCase
class SeleniumAppTest(LiveServerTestCase):
"""
Test my app!
"""
host = 'app'
Since we are running tests inside the app
container, we would like the Selenium to connect to the live development server on http://app:{random_port}
.