Simplify running and testing your tests and maybe even get more people to run and use them.
Add a simple but easy-to-use docker-compose orchestration framework using a Selenium Standalone browser container to your browser test projects. View the tests using the included Virtual Network Computing (VNC) Server.
Use it locally to simplify using and testing your tests.
Use it in Continuous Integration/Continuous Deployment (CI/CD) to simplify workflows and keep the logic with your tests.
#docker-compose #unixshellprogramming #docker-selenium
In the continuation of this three part series, I will show you how you can add a docker-compose framework to your automated browser tests (e.g. end-to-end, acceptance) with a single command to spin it up, run it, and tear it all back down.
We'll cover and practice some docker-compose concepts and Unix shell programming.
This is Part 2 where we will continue to cover The How of adding this framework, specifically...
- The
Dockerfile- The Don't Repeat Yourself (DRY) set of
docker-composefiles
You will want a Dockerfile to build the Docker image for your
browser tests project. You may already have one.
For your docker-compose framework, you will want to do these two
things in your Dockerfile...
- Use the
runtestsscript that you just added as theCMDfor your image so that it has your defaults and waits on the Selenium browser to be fully up before running the tests - Use
CMDand notENTRYPOINTso that it is easier to override and specify a command to run to make your docker-compose framework more flexible
Here's an example of a simple Dockerfile for a .NET/C# Selenium
browser test project....
FROM mcr.microsoft.com/dotnet/sdk:5.0
COPY . .
WORKDIR /BrowserTests
CMD ./script/runtestsI find that in life, the best principles are universal. For instance,
the principle of Don't Repeat Yourself which works so well when
telling stories also works well in maintaining docker-compose files.
docker-compose allows you to specify multiple docker-compose files
which can override previous configurations. This can remove duplication
and provide greater flexibility by simply adding another docker-compose
file. This also lets you make smaller, more cohesive and portable
docker-compose files.
At the least, you will want two docker-compose files...
- A
docker-compose.ymlfile for your browser tests' default specification - A
docker-compose.selenium.ymlfile for adding the Selenium Standalone browser
Start with the base docker-compose.yml for your tests.
This should be the base or "production" version for your tests (i.e. used in CI/CD).
Here's an example docker-compose.yml for your browser tests...
version: '3.4'
services:
browsertests:
image: "your-org/your-browser-tests:${BROWSERTESTS_TAG:-latest}"
container_name: ${BROWSERTESTS_HOSTNAME:-browsertests}This is a pretty simple docker-compose file that defines a
browsertests service for your-org/your-browser-tests image.
The :${BROWSERTESTS_TAG:-latest} allows you to specify a tag
for your image using the BROWSERTESTS_TAG environment variable.
If it is not specified, it uses the default value latest. This
is useful for testing images when developing the tests.
The container_name: ${BROWSERTESTS_HOSTNAME:-browsertests} allows
you to specify a container name and hostname for networking using
the BROWSERTESTS_HOSTNAME environment variable. If it is not
specified, it uses the default value browsertests. This can
be useful in CI/CD if unique running container names are needed.
I picked up this ability to use and assign default values to environment variables in docker-compose from the Docker documentation on environment variables.
However, this is a shell programming technique, yet another good reason to know some shell.
Now add the docker-compose.selenium.yml configuration file.
Here's an example docker-compose.selenium.yml file...
version: '3.4'
services:
browsertests:
environment:
- BROWSER=${BROWSER:-chrome}
- REMOTE=http://${SELENIUM_HOSTNAME:-seleniumbrowser}:4444/wd/hub
- REMOTE_STATUS=http://${SELENIUM_HOSTNAME:-seleniumbrowser}:4444/wd/hub/status
depends_on:
- seleniumbrowser
seleniumbrowser:
image: ${SELENIUM_IMAGE:-selenium/standalone-chrome:latest}
container_name: ${SELENIUM_HOSTNAME:-seleniumbrowser}
shm_size: 2gb
volumes:
- /dev/shm:/dev/shm
ports:
- "5900:5900"
- "7900:7900"
healthcheck:
test: ["CMD-SHELL", '/opt/bin/check-grid.sh --host 0.0.0.0 --port 4444']
interval: 15s
timeout: 30s
retries: 5This one is not so simple, but demonstrates how docker-compose
files can be additive and override previous files. We would call
these two files in this order...
docker-compose -f docker-compose.yml -f docker-compose.selenium.yml <docker command>
This order is important because the docker-compose.selenium.yml adds on and/or
overrides settings from your docker-compose.yml. Files you list later on the
command line override those you listed previously.
You can learn more about multiple compose files from the Docker documentation on multiple compose files
Start with configuring the seleniumbrowser service...
Although it's later in the .yml file, you start with the docker-compose
service for the Selenium browser because information on its configuration
is needed for setting environment variables in the service for your tests.
This is how you will connect the Selenium browser to your browser tests.
This part below defines the seleniumbrowser service, and...
- Lets you specify a specific selenium standalone image
(i.e. chrome, firefox, specific version, etc.) using the
SELENIUM_IMAGEenvironment variable or setsselenium/standalone-chrome:latestas the default - Lets you specify a container name which would be used
as the hostname for the Selenium browser or sets the
default
seleniumbrowser(you will need to give this address to your browser tests service) - Sets the defaults required by Selenium for the
shmandvolumes(storage)
seleniumbrowser:
image: ${SELENIUM_IMAGE:-selenium/standalone-chrome:latest}
container_name: ${SELENIUM_HOSTNAME:-seleniumbrowser}
shm_size: 2gb
volumes:
- /dev/shm:/dev/shmNext you add the VNC server port mapping to your localhost so that you can see the tests running...
ports:
- "5900:5900"
- "7900:7900"Port
5900is for connection with a VNC client at vnc://localhost:5900Port
7900is for connection with the noVNC browser client at http://localhost:7900/
Now as good practice, we add a health check to our seleniumbrowser...
healthcheck:
test: ["CMD-SHELL", '/opt/bin/check-grid.sh --host 0.0.0.0 --port 4444']
interval: 15s
timeout: 30s
retries: 5Now add the browsertests service configuration...
Now that you have configured the seleniumbrowser service,
you will use some of this information to add additional
configuration to your browsertests service and connect
the two docker-compose services.
This section adds the environment variable settings that you will want....
environment:
- BROWSER=${BROWSER:-chrome}
- REMOTE=http://${SELENIUM_HOSTNAME:-seleniumbrowser}:4444/wd/hub
- REMOTE_STATUS=http://${SELENIUM_HOSTNAME:-seleniumbrowser}:4444/wd/hub/statusThis sets the REMOTE_STATUS environment variable which is used by your
runtests script.
You should also have an environment variable implemented in your browser tests that lets you specify the URL of the remote Selenium browser and possibly the type of browser (e.g. chrome)
This section tells docker-compose to ensure that the seleniumbrowser
service must be running whenever you run your browsertests service...
depends_on:
- seleniumbrowserThis dependency allows you to run just the browsertests service
but have it also start the seleniumbrowser service. You will use
this in your dockercomposerun helper script.
I put this
docker.compose.selenium.ymlfile together over several iterations using the Selenium Docker documentation for the specific configuration values.
Test your docker-compose files to ensure that they work and run your tests...
-
Make sure you have your browser tests image already built if you are pulling the image in your
docker-compose.ymlfile -
To run your
docker-composeframework, use the command...docker-compose -f docker-compose.yml -f docker-compose.selenium.yml run browsertests -
Check that you can see your tests running in the VNC server
-
To tear down your
docker-composeframework, use the command...docker-compose -f docker-compose.yml -f docker-compose.selenium.yml down
This is the end of Part 2. Continue to Part 3.