As you move more towards continuous testing, it becomes important to be able to execute your automated tests rapidly in multiple environments. Docker is perfect for this, providing a simple way to execute your tests on any system, against any environment. Selenified works perfectly inside a Docker container, allowing functional tests to be easily integrated into any DevOps pipeline.

The Setup

In order to build a Docker container to run your tests, only a few things need to be set up. Overall, it’s pretty simple if you have some familiarity with docker. If not, check out some of our many docker posts.
First, you need to create a Dockerfile, which needs to be configured to be able to execute your tests. Personally, I like to copy my tests onto the docker container when building it and keep my docker containers versioned, to match with my source code. Alternatively, you could also keep your tests local, and just mount them to your container for execution. Additionally, you’ll need to set up the container with the appropriate build tool, and the browser you want to execute them with (or no browser if running with HtmlUnit). My docker container looks something like below:

FROM gradle:5.2.1-jdk8

#######
# RUN INSTRUCTIONS
#######
# execute all tests on the default environment (staging), using chrome browser headlessly, in 5 threads
# `docker run`
# additional params can be set
# `TEST_URL` can be passed in to change the system under test
# `INCLUDE_GROUPS` can be passed to only run tests with a group. This can be comma separated for multiple groups
# `EXCLUDE_GROUPS` can be passed to excluding running tests with a group. This can be comma separated for multiple groups
# `BROWSER` the browser to run tests on. This will fail pretty spectacularly if changed, as only chrome is installed on this container
# `THREADS` how many tests should be run in parallel
# to use these additional params, call something like
# `docker run -e TEST_URL=http://somenewsite -e INCLUDE_GROUPS=smoke

#general env settings
ENV JAVA_OPTS=""

WORKDIR /app

#variables to set for run execution
ENV TEST_URL=""
ENV INCLUDE_GROUPS=""
ENV EXCLUDE_GROUPS=""
ENV BROWSER="Chrome"
ENV THREADS=5

#Install chrome
USER root
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update -qqy \
    && apt-get -qqy install google-chrome-stable \
    && rm /etc/apt/sources.list.d/google-chrome.list \
    && rm -rf /var/lib/apt/lists/ */var/cache/apt/* \
    && sed -i 's/"$HERE\/chrome"/"$HERE\/chrome" --no-sandbox --disable-dev-shm-usage/g' /opt/google/chrome/google-chrome

#copy over only what we need
COPY build.gradle /app
COPY settings.gradle /app
COPY src/test src/test
COPY docker-entrypoint.sh /usr/local/bin

#setup results mount
VOLUME ["/app/reports"]

CMD ["docker-entrypoint.sh"]

The above example is for Gradle, but would look almost identical to one for Maven (just different FROM and ENV variables). You should notice that all of the parameters that could be passed in to modify our tests are stated as ENV variables¬†so that they can be modified to facilitate testing. Because we have installed Chrome, we’ve set up the default browser to be Chrome.
The last step is to set up our entry point, which tells the Docker container how to run the tests.

#!/bin/bash

gradle clean selenified \
    -Dbrowser=${BROWSER} \
    -Dheadless=true \
    -Dthreads=${THREADS} \
    ${INCLUDE_GROUPS:+"-Dgroups.include=${INCLUDE_GROUPS}"} \
    ${EXCLUDE_GROUPS:+"-Dgroups.exclude=${EXCLUDE_GROUPS}"} \
    ${TEST_URL:+"-DappURL=${TEST_URL}"}

export RESULT=$?
cp -r /app/build/reports/tests/selenified/* /app/reports

exit $RESULT

This file gets kicked off each time we perform a Docker run, and handles passing run-time variables into our framework for execution. You’ll notice all variables defined in the docker container build are passed in here, pulling in the default, and allowing an override. They should match what weset upp in the Dockerfile, and if using a different build tool (such as Maven), should also be updated to match.

Test Execution

Executing your tests now becomes simple. All you need to do is run your docker container, and if desired, pass in parameters to override any defaults set. For example, to launch the tests using the default (pre-set) parameters, first, build your container with your tests

docker build -t selenified .

Then execute it

docker run -t selenified

And, if we wanted to run different sets of tests, or change any of our parameters, we simply pass it in with the -e option. So in order to run only our smoke tests, we would executed

docker run -t selenified -e INCLUDE_GROUPS='smoke'

And that’s it, very simple test execution within a Docker container.

Obtaining Results

The largest issue with keeping your tests on the docker container, is that the results are kept there as well. In order to combat this, I like to setup a mount to my docker container in order to get the results locally. The Dockerfile above is actually setup with /app/reports as a mount point for this exact reason. If you run docker with the below command

docker run -t selenified -v 'reports:/app/reports'

When our tests finish running, the reports will be in the local reports directory

Wrap-up

With this, it’s easy to call these steps locally as a developer, build the container and run within CI or CD, or even have others just pull the container to re-run tests against a different environment. Docker really does assist for testing, and make CT easier!

As always, drop your thoughts below.

Leave a comment

Your email address will not be published. Required fields are marked *

X