Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save brianjbayer/55ed6e732d96699274f89d4ed6e674d5 to your computer and use it in GitHub Desktop.
Save brianjbayer/55ed6e732d96699274f89d4ed6e674d5 to your computer and use it in GitHub Desktop.
Part 2 - Add a docker-compose Framework to Your Browser Tests

Add a docker-compose Framework to Your Browser Tests (Part 2 of 3)

The River in the Flats Cleveland, Ohio - Wendy Bayer


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-compose files

Skip to Part 1 or Part 3


You Want a Dockerfile...

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...

  1. Use the runtests script that you just added as the CMD for your image so that it has your defaults and waits on the Selenium browser to be fully up before running the tests
  2. Use CMD and not ENTRYPOINT so 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/runtests

You Want a DRY Set of docker-compose Files

I 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...

  1. A docker-compose.yml file for your browser tests' default specification
  2. A docker-compose.selenium.yml file for adding the Selenium Standalone browser

Add a docker-compose.yml File

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}

How It Works

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.


Add the docker-compose.selenium.yml File

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: 5

How It Works

This 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_IMAGE environment variable or sets selenium/standalone-chrome:latest as 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 shm and volumes (storage)
  seleniumbrowser:
    image: ${SELENIUM_IMAGE:-selenium/standalone-chrome:latest}
    container_name: ${SELENIUM_HOSTNAME:-seleniumbrowser}
    shm_size: 2gb
    volumes:
      - /dev/shm:/dev/shm

Next you add the VNC server port mapping to your localhost so that you can see the tests running...

    ports:
      - "5900:5900"
      - "7900:7900"

Port 5900 is for connection with a VNC client at vnc://localhost:5900

Port 7900 is 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: 5

Now 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/status

This 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:
  - seleniumbrowser

This 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.yml file together over several iterations using the Selenium Docker documentation for the specific configuration values.


Test it

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.yml file

  • To run your docker-compose framework, 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-compose framework, 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment