Docker Selenium Tutorial for Parallel Testing on Selenium Grid

Docker Selenium is highly used by test teams to run their tests in parallel on Selenium Grid. In this article, I will explain to you how to use docker selenium and selenium grid infrastructure to run your tests in parallel. You can also find the system architecture and meaning of selenium grid, docker selenium, and docker network. Let’s get started!

What is Selenium Grid

Selenium Grid is a project created for executing tests on different browsers and operating systems. It has a simple architecture: A hub and one or more nodes. You run your test across the hub and the hub distributes the test across different browsers.

docker selenium

Advantages of Selenium Grid:

  • Reduces execution time with distributed testing.
  • Allows cross-browser and platform testing.

Problems of Selenium Grid:

  • Hard to configure (Installing Java, downloading selenium standalone server, installing related browsers and drivers, etc.)
  • Hard to manage (testing different versions of different browsers)
  • Resource usage.

What is Docker Selenium?

It uses the same architecture but each component, hub, and nodes, is a separate container.

What are the advantages of Docker Selenium?

  • We got rid of all the dependencies are mentioned above.
  • Does not use system resources like VM’s so it’s lightweight.
  • We can easily manage all the version complexity with the docker registry.

Docker Selenium Configuration

To be able to use docker selenium, the first thing you need to do is docker installation. If Docker is not already installed on your system, please follow the documentation for installation steps. There are different ways to configure selenium. In this tutorial, I will show the docker network and docker-compose methods.

Docker Network

Create a Docker Network

Use docker network create <NETWORK_NAME> command to create a network so that the containers can communicate with each other.

docker selenium tutorial

List networks with docker network ls

docker-selenium

Other networks come with docker installation.

If you notice, I did not provide any parameters while creating the network, so the “bridge” network was used by default. There are other network types like Host, Overlay, and Macvlan for different use cases. For example, if you have containers on different Docker hosts, you will need an Overlay network.

You may ask “Why we defined a new bridge network instead of using the default bridge driver?” The reason is user-defined bridges have some advantages over the default bridges like providing automatic DNS resolution between containers. If I use the default network, I should link the containers explicitly by using “–link” parameter which is legacy.

docker-selenium tutorial

For now, there is no container in our network.

Create a Docker Hub

Use docker run to create a hub.

$ docker run -d -p 4444:4444 --net grid --name selenium-hub selenium/hub:3.11.0-dysprosium

d: detached mode. The container starts in the background with this command. You don’t see any output from the container console.

p: publish port (we bind the port 4444 of the container to 4444 of the docker host)

net: specify which network we add the container

name: specify a name of the container and the last parameter is the image name used when creating the container.

docker compose

What happened under the hood?

selenium docker

Step-1: The Docker client contacted the Docker daemon.

Step-2: The Docker daemon pulled the “hub” image from the Docker Hub.

Step-3: The Docker daemon created a new container from that image.

If you want to see the logs of the container, you can use the below command.

docker logs <CONTAINER_ID>

Images build for docker-selenium are listed below and available in Docker  Hub:

  • base
  • hub
  • node-base
  • node-chrome
  • node-firefox
  • node-chrome-debug
  • node-firefox-debug
  • standalone-chrome
  • standalone-firefox
  • standalone-chrome-debug
  • standalone-firefox-debug

node-{Browser Name} and node-{Browser Name}-debug cannot be used alone; they must be connected to a hub. Debug versions include a VNC server to visually debug the browser during the test.

List available images with docker images

selenium docker example

Tagging convention for images is like this;

<Major>.<Minor>.<Patch>-<Chemical Element in Alphabetical order>

When I wrote this tutorial the latest tag was “dysprosium”. If you don’t specify a tag for an image, it will download the latest one.

Now, list running containers by typing docker ps

docker selenium example

Check http://localhost:4444/grid/console

docker tutorial

As you see above, our hub is up and running.

Create a Docker Node

Create a chrome node:

$ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome:3.11.0-dysprosium

e: stands for environment variables. NODE_MAX_SESSION, NODE_MAX_INSTANCE etc. are defined in this part. You can see other environment variables by using docker inspect <IMAGE_ID> command.

v: This option suggested in official documentation to use host’s shared memory.

Similarly, docker daemon could not find chrome image, downloaded, start the container and print the id.

Let’s add one Firefox node:

$ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox:3.11.0-dysprosium

Same thing. The only difference is the image name. We simply replaced Chrome with Firefox. :)

We have one hub, one chrome node, and one Firefox node. Let’s check them by docker images command.

selenium grid docker

Run docker ps to check their status.

If we look at our network again, we should see our newly added containers.

chrome containers

Our setup is ready. Let’s execute some tests on this configuration.

Execution of Tests

You can use the project mentioned here:

http://www.swtestacademy.com/selenium-parallel-tests-grid-testng/

Change only two things in the code. Enable RemoteWebdriver section in TLDriverFactory and edit testng.xml like below;

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" >
    <listeners>
        <listener class-name="com.InvokedMethodListener"></listener>
    </listeners>
    <test name="com.FirstTest">
        <parameter name="browser" value="chrome"/>
        <classes>
            <class name="com.FirstTest">
                <methods>
                    <include name="GOOGLE0" />
                    <include name="GOOGLE2" />
                    <include name="GOOGLE3" />
                    <include name="GOOGLE4" />
                </methods>
            </class>
        </classes>
    </test>
    <test name="com.SecondTest">
        <parameter name="browser" value="firefox"/>
        <classes>
            <class name="com.SecondTest">
                <methods>
                    <include name="GOOGLE1" />
                    <include name="YANDEX" />
                </methods>
            </class>
        </classes>
    </test>
</suite>

Thus, we execute FirstTest and SecondTest in parallel. The FirstTest will use chrome while the SecondTest will use firefox.

How to See the Running Tests Visually in Docker Containers

Stop nodes by using docker stop <CONTAINER_ID>

Run the containers, but use node-{Browser Name}-debug versions for this time.

docker run -d -P -p 5900:5900 --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome-debug:3.11.0-dysprosium
docker run -d -P -p 5901:5900 --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox-debug:3.11.0-dysprosium

Also, publish the ports. Open a VNC client and try to connect with selected ports. It will ask for a password, type secret

Now, I will make the same configuration with docker-compose.

Docker Compose for Selenium Grid

What is docker compose?

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

Please follow docker compose installation.

docker-compose file

Create a file called docker-compose.yml as follows with your favorite text editor;

version: "3"
services:
  selenium-hub:
    image: selenium/hub
    container_name: selenium-hub
    ports:
      - "4444:4444"
  chrome:
    image: selenium/node-chrome
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444
  firefox:
    image: selenium/node-firefox
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444

version: There are several versions of compose file. It can be 1, 2, 2.x 3.x check compatibility matrix

image: determine which container will be used to start container.

container_name: specifies container name

ports: publish port with <HOST:CONTAINER> format

volumes: mount host path to service with <HOST:CONTAINER> format

depends_on: containers start according to dependency order. In our example, chrome and firefox will start after the hub starts.

environment: specifies environment variables. You can see other environment variables of selenium images by using docker image inspect <IMAGE_ID>

Run Docker Compose

docker-compose up -d

Scale Docker Compose

docker-compose up –d ––scale chrome=5

dockerize selenium

selenium grid using docker

You can observe CPU, the memory usage of containers with docker stats

selenium hub docker

How to Stop Docker Containers

docker-compose down

how to use docker selenium

That was a little bit long but I hope you enjoyed reading it.

In the next tutorials, I will try to explain other containerization solutions for selenium like Selenoid and Zalenium. Then I will make a comparison between them.

Keep calm and automate all things. :)
Kaan Sariveli

8 thoughts on “Docker Selenium Tutorial for Parallel Testing on Selenium Grid”

  1. Hi Kaan,
    when i run “docker run -d -p 5900:5900 –link selenium-hub:hub -v /dev/shm:/dev/shm selenium/node-chrome-debug:3.11.0-dysprosium” this command i got
    “docker: Error response from daemon: Cannot link to /selenium-hub, as it does not belong to the default network.” this error, prior to this i am able to perform all tasks.

    Reply
    • Hi Mayur,

      Command in the tutorial was wrong, sorry about that.
      Correct one should be,

      docker run -d –net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome-debug:3.11.0-dysprosium

      The reason you got the error is that we don’t specify the network and docker tried to find the hub in default network which is not exist.

      Could you please try with the new command?

      Thanks,
      Kaan

      Reply
  2. Hello Kaan,

    Whenever we run the debug command for Chrome container. Which port should we use to connect via VNC?

    Reply
    • We have just fixed that part. ;)

      docker run -d -P -p 5900:5900 –net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome-debug:3.11.0-dysprosium
      docker run -d -P -p 5901:5900 –net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox-debug:3.11.0-dysprosium

      Reply
  3. docker-compose.yml mentioned above has validation issue. A colon is reqiired at the end of third line. it has to be “selenium-hub:”. Or else we get an error – “ERROR: yaml.scanner.ScannerError: mapping values are not allowed here”

    Reply
  4. hello is it beneficial to use docker :
    because using other grid methods i was able to execute 6 execution at a time but using docker machine struggle to complete the execution, is that because of the recourse management of the docker that by default docker provide.

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.