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 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 1 where we will cover...
- The What of this framework (i.e. what we will add)
- The start of The How of adding this framework, specifically the first piece which is the
runtests
script
In this 3 part series, you will build this framework by adding...
runtests
script to orchestrate (wait on) a remote browser (i.e. Selenium Standalone)- Project
Dockerfile
to build your browser tests image with a defaultCMD
that can be overridden - Don't Repeat Yourself (DRY) set of
docker-compose
files to orchestrate the browser tests and the Selenium Standalone browser container dockercomposerun
script that can be used locally and in CI/CD that sets up the browser tests and Selenium Standalone containers, runs the browser tests image, and tears it all down, returning the return code from running the browser tests container
To add this framework to your project, you will need to have a way, ideally an environment variable, to configure the URL of the remote (Selenium) browser in your browser tests application
To implement your
runtests
script, you will need to have a simple way of checking the remote status endpoint in the shell of your particular browser tests' base image and the command to run your tests
You will want a runtests
script to wait on the remote
browser (i.e. Selenium Standalone) to be fully up and
ready before running your tests. Although the Selenium
Standalone container may be "up", it still may not be
ready for the tests to run and the tests will fail.
I am pretty sure that I originally got this script from Ruiyu(Ryan) Wang and IIRC he said he got it from "some post on the internet".
It is also based on the Selenium Standalone Container using a bash script to wait for the grid. This is where I got the
curl
command that I will give later and theREMOTE_STATUS
endpoint.
Here's an example of a runtests
script that you can
use and customize. This syntax will work for both
ash
in Alpine/BusyBox and bash
. However, the
wget
command is specific for Alpine and the
bundle exec rspec
is only for Ruby-Rspec.
#!/bin/sh
# This script orchestrates running the browser tests
# with a remote browser if its status point is set
#
# Assumes Alpine (Busybox) and uses wget
if [ ! -z "${REMOTE_STATUS}" ];
then
COUNTER=0
echo "Waiting for ${REMOTE_STATUS} to become available"
until wget --spider -q "${REMOTE_STATUS}" &>/dev/null; do
printf "."
sleep 1
COUNTER=$((COUNTER + 1))
if [ $COUNTER -eq 30 ] ; then
echo "✘"
exit 1
fi
done
echo "✔"
fi
# Run the tests with the underlying testing framework
# (with any passed in args)
bundle exec rspec "$@"
Where to put your script...
You will want a directory in your project for your
runtests
script and the dockercomposerun
script
that you will add later if you do not already have one.
Some people use bin/
, but I prefer that for actual
binaries and use script/
. You do you.
Make sure your script is executable...
Captain Obvious says, you will want to make sure that your
runtests
script is executable (i.e. chmod ug+x runtests
)
The script is intended to be run from the project root directory
(e.g. ./script/runtests
).
The line if [ ! -z "${REMOTE_STATUS}" ];
checks whether the
REMOTE_STATUS
environment variable is set and non-empty and
if so, then enters the wait on remote browser logic. If the
REMOTE_STATUS
environment variable is not set or is empty,
then the wait logic is skipped and the script simply runs
the command to run the tests (for example if running with a
local browser).
The
REMOTE_STATUS
endpoint is the/status
route off of the base URL for your remote Standalone Container browser (e.g. http://localhost:4444/wd/hub/status).
The line until wget --spider -q "${REMOTE_STATUS}" &>/dev/null; do
starts an "until" loop which checks every second 30 times if the
REMOTE_STATUS
endpoint shows ready.
Here we are using the wget --spider -q "${REMOTE_STATUS}"
command
to check if the endpoint is ready since this an Alpine/BusyBox base
image.
To use a curl command instead...
For a base-image with the curl
command present, you can use...
curl -fsSL "${REMOTE_STATUS}"
If the endpoint check does not return ready after the 30 tries, the script exits with a non-zero return code indicating failure.
If the endpoint check does return ready, then the loop exits and the
script runs the command to run the tests, here bundle exec rspec "$@"
since this is a Ruby-RSpec example.
The "$@"
argument contains any arguments passed to the runtests
scripts thus forwarding them on to the command to run the tests.
This allows you to pass arguments to the runtests
command that
are supported by the underlying testing framework (e.g. RSpec)
for example, passing "filters" to run or exclude
specific tests.
Put any default arguments that you want, particularly for CI/CD, for the command you use to run your tests (e.g.
bundle exec rspec --format documentation "$@"
). in yourruntests
script for consistency, a single source of truth, and easier maintenance and testing
Test your runscript
script to ensure that it...
- Runs locally when
REMOTE_STATUS
is not set, for exampleREMOTE_STATUS= ./script/runtests
- Fails if the
REMOTE_STATUS
is set but not available, for example...REMOTE_STATUS=foo ./script/runtests
- Runs the tests when the
REMOTE_STATUS
is available, for example...docker run -d -p 4444:4444 -p 5900:5900 -p 7900:7900 -v /dev/shm:/dev/shm selenium/standalone-chrome REMOTE='http://localhost:4444/wd/hub' REMOTE_STATUS=${REMOTE}/status BROWSER=chrome ./script/runtests
- Passes any arguments to the command to run your tests, for example...
./script/runtests --dry-run
This is the end of Part 1. Continue to Part 2.