Dynamic Selenium Grid Cluster Deployment and Video Recording Integration

TRIVE DEVOPS
5 min readJun 12, 2023

--

Selenium WebDriver is a collection of language-specific bindings to drive a browser, create robust, browser-based regression automation suites and tests, and scale and distribute scripts across environments.

Selenium Grid allows the execution of WebDriver scripts on remote machines by routing commands sent by the client to remote browser instances. Complementing this with parallel test execution dramatically reduces total test and pipeline execution times.

In this article, we will create a 3 Node Cluster that can run 24 test sessions simultaneously. With this setup, chrome instances will be created on demand as docker containers with video recordings of the sessions saved and will make your Selenium Grid dynamic.

Prerequisites:

  • At least 1 VM as a Node (3 VMs in our case)
  • Docker and docker-compose installed

Installation

We use docker to deploy Selenium Dynamic Grid on both test and production environments. It is possible to add new nodes later (grid instances) to increase max concurrency or availability.

1. Create docker-compose.yml

Docker compose file below is taken from the official documentation.

version: "3"
services:
node-docker:
image: selenium/node-docker:4.8.1-20230221
volumes:
- ./assets:/opt/selenium/assets #For video recordings
- ./config.toml:/opt/bin/config.toml #Mount configuration file
- /var/run/docker.sock:/var/run/docker.sock #Grid to run docker commands
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
shm_size: 2gb #Increase shm_size to prevent memory problems

selenium-hub:
image: selenium/hub:4.8.1-20230221
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"

As you can see from the compose file above, we both have node-docker and selenium-hub services. Hence, this first machine will work both as a hub (to receive and distribute session requests) and a node (to execute test sessions). We choose this configuration because selenium-hub is not very resource-demanding.

2. Create configuration file — config.toml

[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
"selenium/standalone-chrome:4.8.1-20230306", "{\"browserName\": \"chrome\"}"
# "selenium/standalone-chrome:4.10.0-20230607", "{\"browserName\": \"chrome\"}"
]
# URL for connecting to the docker daemon
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-4.3.1-20230306"

In configs section, we choose only standalone-chrome image because we only use Chrome browser in our tests. If you need Firefox or Edge, you can add those images like the commented line.

3. Run docker-compose up and check UI

After you run docker-compose up command, the selenium hub should be up and running. You can check your hub at http://your-ip-adress:4444/ui to see nodes and sessions.

Figure 1 — Selenium Hub UI

By default, concurrency on selenium nodes is equal to the number of CPUs of the machine.

To make session recording working, you need to provide "se:recordVideo": true parameter in the WebDriver options. This is configured inside the test code, so contact with the QA team if necessary, to add the parameter.

4. Add other nodes to cluster

To add new nodes to the cluster, create docker-compose.yaml and config.toml files like the ones below.

docker-compose.yaml

version: "3"
services:
node-docker:
image: selenium/node-docker:4.8.1-20230221
volumes:
- ./assets:/opt/selenium/assets
- ./config.toml:/opt/bin/config.toml
- /var/run/docker.sock:/var/run/docker.sock
environment:
- SE_EVENT_BUS_HOST= <SELENIUM-HUB-IP-ADDRESS>
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
shm_size: 2gb
ports:
- "5901:5901" #You can change the port config if necessary

config.toml

[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
"selenium/standalone-chrome:4.8.1-20230306", "{\"browserName\": \"chrome\"}"
]

# URL for connecting to the docker daemon
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-4.3.1-20230306"

# Uncomment the following section if you are running the node on a separate VM
# Fill out the placeholders with appropriate values
[server]
host = "NODE'S-OWN-IP-ADDRESS"
port = "5901"

As you can see, we can add many nodes with a few simple configuration changes. When you run docker-compose up, nodes will join to the cluster, and the concurrency count will increase, like the figure below.

Figure 2 — Selenium Hub UI after Nodes joined

You can click the sessions menu on the left-hand side to watch ongoing test sessions with your browser. Selenium hub will load balance test executions by default.

Figure 3 — Active Sessions Running

Since test scenarios will be distributed to nodes, session video recordings will be distributed also. If you want to show your video recordings in the test report, you might want to figure out a solution to collect all those recordings.

Bonus: Synchronizing Video Recordings

Since test sessions and video recordings are distributed across all nodes, the machine you execute test commands or selenium hub can’t know in which node your SessionID’s video recording is saved.

To solve this problem, we can use rsync to synchronize all 3 assets directories to our report server.

#!/bin/bash

# Set the source and destination directories
SRC_DIR=/PATH/TO/VIDEO/RECORDINGS/ASSETS
DEST_HOST=username@DESTINATION-IP-ADDRESS
DEST_DIR=/var/www/html/reports/selenium-video-recordings/
PASSWORD=password

# Use rsync to copy any new subdirectories from the source to the destination
sshpass -p "$PASSWORD" rsync -avz --exclude="..." -e 'ssh -o StrictHostKeyChecking=no' "$SRC_DIR" "$DEST_HOST:$DEST_DIR"

The bash script above utilizes rsync to synchronize the local recording directory to the remote server, which we use to collect all 3 Nodes’ recordings and host them for test reports in one place. You can run this bash script with crontab (like every 10 minutes) on all nodes.

After some test executions, recordings might fill up some disk space. Make sure that you monitor your disk size or set a retention policy to save your disk space.

We hope this article has been helpful in setting up your own dynamic Selenium Grid cluster. If you have any questions or feedback, please don’t hesitate to leave a comment or like this article. We’d love to hear from you! :)

Stay tuned for more updates!

--

--