Skip to content

Instantly share code, notes, and snippets.

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

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

Cleveland Browns Stadium Cleveland, Ohio - Brian 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 conclusion 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 3 where we will cover...

  • The conclusion of The How of adding this framework, specifically the dockercomposerun script (the final piece)
  • Using your newly added docker compose framework

Skip to Part 1 or Part 2


You Want a dockercomposerun Script to Run it All

Because laziness is a virtue in computer science, you want a dockercomposerun script that sets up, runs, and tears down your docker-compose framework for you. You can then use this single command locally or in CI/CD.

And you value transparency, especially in CI/CD, so you will want to have the script output version and environment information. This is especially helpful when debugging any issues.

Finally, to ensure that the CI/CD job fails when your tests fail, you will want to capture the return code of the test run and return that as the return code for your dockercomposerun command.

To make your dockercomposerun script more flexible and usable, you will pass any arguments to the script to the docker-compose run command so that this command overrides the runtests CMD in your Dockerfile


Add a dockercomposerun Script

Here is a basic dockercomposerun script that you can add...

#!/bin/sh
# This script runs the project docker-compose framework.
#
# - The arguments to this script are passed to the browsertests service
#   as command override
#
# - Any environment variables set when calling this script are passed
#   through to the docker-compose framework
#   (e.g. configuration other than the defaults
#

# Exit script on any errors
set -e

echo ''
echo "ENVIRONMENT VARIABLES..."
env
echo ''

echo 'DOCKER VERSION...'
docker --version
docker-compose --version
echo ''

echo 'DOCKER-COMPOSE COMMAND...'
docker_compose_command='docker-compose -f docker-compose.yml -f docker-compose.selenium.yml '
echo "...COMMAND: [${docker_compose_command}]"
echo ''

echo 'DOCKER-COMPOSE CONFIGURATION...'
$docker_compose_command config
echo ''

echo 'DOCKER-COMPOSE PULLING...'
set +e
$docker_compose_command pull
echo '...Allowing pull errors (for local images)'
set -e
echo ''

echo 'DOCKER IMAGES...'
docker images
echo ''

echo "DOCKER-COMPOSE RUNNING [$@]..."
# Allow to fail but catch return code
set +e
$docker_compose_command run browsertests "$@"
run_return_code=$?
# NOTE return code must be caught before any other command
set -e
echo ''

if [ $run_return_code -eq 0 ]; then
    run_disposition='PASSED'
else
    run_disposition='FAILED'
fi
echo "...RUN [${run_disposition}] WITH RETURN CODE [${run_return_code}]"
echo ''

echo 'DOCKER-COMPOSE DOWN...'
$docker_compose_command down
echo ''

echo "EXITING WITH ${run_disposition} RUN RETURN CODE ${run_return_code}"
exit $run_return_code

How It Works

This is pretty basic Unix shell programming because... well... me.

The set -e command ensures that the script will exit with an error code on any unexpected errors. We never want to risk that our tests falsely "pass" if they do not actually run.

The env command outputs the current environment variables for transparency.

The docker --version and docker-compose --version commands output the respective version information again for transparency.

The command docker_compose_command='docker-compose -f docker-compose.yml -f docker-compose.selenium.yml ' assigns the sequenced calling of the framework's docker-compose files to a local variable. This is that Don't Repeat Yourself principle in practice again.

This is also useful to conditionally add another docker-compose file...

This is also useful if you need to conditionally add another docker-compose file for reasons.

Here's an example where I conditionally add a development environment docker-compose file if a browser tests image is specified...

echo 'DOCKER-COMPOSE COMMAND...'
docker_compose_command='docker-compose -f docker-compose.yml -f docker-compose.selenium.yml '
if [ ! -z ${BROWSERTESTS_IMAGE} ]; then
  echo "...Using Development Environment with Image [${BROWSERTESTS_IMAGE}]"
  docker_compose_command="${docker_compose_command} -f docker-compose.dev.yml "
fi
echo "...COMMAND: [${docker_compose_command}]"
echo ''

The $docker_compose_command config command outputs the final docker-compose configuration with all additions and overrides for transparency.

This following block pulls the images but uses set +e to unset the exit-on-failure setting to allow pull failures for local images. It then sets the exit-on-failure setting.

echo 'DOCKER-COMPOSE PULLING...'
set +e
$docker_compose_command pull
echo '...Allowing pull errors (for local images)'
set -e
echo ''

This explicit pulling of images means that the script will pull any name:tag images if they exist in your remote container registry (e.g. Docker Hub) overriding any local images with the name:tag. This behavior is intended for CI/CD where control and certainty is required.

TIP: To test local images, use a tag that does not exist in your container registry.

Again for transparency and debugging (especially with local images), the docker images command outputs all the docker images present.

This following block runs any supplied command line arguments in the browsertests container. This allows you to override the default runtests command in your image. If there are no arguments, it runs the default Dockerfile CMD (i.e. the runtests script.)

echo "DOCKER-COMPOSE RUNNING [$@]..."
# Allow to fail but catch return code
set +e
$docker_compose_command run browsertests "$@"
run_return_code=$?
# NOTE return code must be caught before any other command
set -e
echo '

It also once again unsets exit-on-failure so that the docker-compose run can fail without the script exiting. run_return_code=$? stores the return code of the run (e.g. tests) to return it at the end of the script.

The script then uses the run_return_code to set and output a 'PASSED' or 'FAILED' local variable in this following block...

if [ $run_return_code -eq 0 ]; then
    run_disposition='PASSED'
else
    run_disposition='FAILED'
fi
echo "...RUN [${run_disposition}] WITH RETURN CODE [${run_return_code}]"
echo ''

The $docker_compose_command down command shuts down and cleans up the docker-compose framework.

Finally, the exit $run_return_code command exits with the value of the stored run_return_code indicating if the run passed or failed.


Test it

Test your dockercomposerun command and your framework to ensure that they work and run your tests.

Be sure to...

  • Make sure you have your browser tests image already built if you are pulling (and not building) the image in your docker-compose.yml file

  • Use the script's output to verify and debug your script and framework

Test that...

  1. Your defaults work, for example...

    ./script/dockercomposerun
    
  2. Your environment variables work, for example...

    SELENIUM_IMAGE=selenium/standalone-firefox  BROWSERTESTS_TAG=foo ./script/dockercomposerun
    
  3. You can supply run commands to override the default runtests command, for example to run your framework interactively...

    ./script/dockercomposerun sh
    

Use Your Framework

Now that you have added your docker-compose framework, you can use it in many ways.

  • You can use it to run and develop your tests more easily locally

    • Use the BROWSERTESTS_TAG environment variable to run and test your own images
  • You can use it in your CI/CD framework to simply your workflows for running the tests, this is especially useful if several applications run your tests as acceptance tests as part of their CI/CD

    • Here's an example from one of my projects where I use dockercomposerun to simplify my GitHub Actions CI...
      run-tests-default-chrome:
        needs: build-deploy
        runs-on: ubuntu-latest
      
        steps:
          - uses: actions/checkout@v1
          - name: dockercomposerun (Run tests) with defaults
            run: ./script/dockercomposerun
      
      run-tests--specified-firefox:
        needs: build-deploy
        runs-on: ubuntu-latest
        env:
          BROWSER: firefox
          SELENIUM_IMAGE: selenium/standalone-firefox:latest
      
        steps:
          - uses: actions/checkout@v1
          - name: dockercomposerun (Run tests) with Firefox
            run: ./script/dockercomposerun
  • You can also use it with the command override ability to perform actions in your container such as linting and static security scanning, for example...

    ./script/dockercomposerun bundle exec rake rubocop
    ./script/dockercomposerun bundle exec rake bundle:audit
    

This concludes this series on adding a docker-compose framework to your browser tests project.

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