As listed in main post and continue to Part 1, we will focus on setting up Selenium Grid using Docker in this Part 2 post.
Introduction
Docker is an open-source containerization platform that makes it easy to create, deploy, and run applications in a secure manner using containers. Docker provides virtualization at the Operating System (OS) level. All the software parts in Docker are organized in Containers.
When it comes to Selenium automation testing, it is important that a test run in one execution environment does not hinder the execution of tests run in another test environment (s). Hence, automation tests should be run in isolation, and Docker helps in realizing this âessentialâ requirement.
Scalable and Reliable
Less overhead of installations
Improved Security
Lesser chances of discrepancies
Prerequisites
Make sure you have these below before started:
Docker: latest release
Yes, that's only it đ.
Set up Selenium Grid with Docker - Standalone mode
There are 3 docker images for Chrome, Firefox and Edge used in this example.
They will use port 4444 by default for server and 7900 for NoVNC, so to use all 3 without error in allocated ports, mapping new ports need to be done.
Start Docker containers
Start Chrome standalone with port 4445
docker run -d -p 4445:4444 -p 7901:7900 --shm-size="2g" selenium/standalone-chrome:4.7.2-20221219
Container exposed on port http://localhost:4445
NoVNC (allow users inspect visually container activity with their browser) exposed on port 7901
For an image that contains a browser please use the flag --shm-size=2g to use the host's shared memory
In order to prevent pushing up to existing tags and breaking existing functionality, should use tagging convention
selenium/standalone-browserName-<Major>.<Minor>.<Patch>-<YYYYMMDD>
Start Firefox standalone with port 4446
docker run -d -p 4446:4444 -p 7902:7900 --shm-size="2g" selenium/standalone-firefox:4.7.2-20221219
Container exposed on port http://localhost:4446
NoVNC exposed on port 7902
Start Edge standalone with port 4447
docker run -d -p 4447:4444 -p 7903:7900 --shm-size="2g" selenium/standalone-edge:4.7.2-20221219
Container exposed on port http://localhost:4447
NoVNC exposed on port 7903
No need to pull image in advance as Docker will pull that image if it was not existed locally
And here is how they are in Docker Desktop (3 containers for 3 standalone)
Standalone Chrome at http://localhost:4445
Standalone Firefox at http://localhost:4446
Standalone Edge at http://localhost:4447
Point your test to exposed ports
Point RemoteWebDriver in your test to corresponding url.
case "chrome":
ChromeOptions chromeOptions = new ChromeOptions();
driver = new RemoteWebDriver(new URL("http://localhost:4445"),chromeOptions);
break;
case "firefox":
FirefoxOptions firefoxOptions = new FirefoxOptions();
driver = new RemoteWebDriver(new URL("http://localhost:4446"),firefoxOptions);
break;
case "edge":
EdgeOptions edgeOptions = new EdgeOptions();
driver = new RemoteWebDriver(new URL("http://localhost:4447"),edgeOptions);
break;
There is an example that I have already written in this repo: https://github.com/trongtuyen96/selenium-grid-docker-zalenium
Head to /test/java/DockerStandaloneTest.java for more details. To execute the test properly, you need to run the DockerStandalone.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="DockerStandaloneTest_Suite">
<test name="ChromeTest">
<parameter name="browser" value="chrome"/>
<classes>
<class name="DockerStandaloneTest"/>
</classes>
</test>
<test name="FirefoxTest">
<parameter name="browser" value="firefox"/>
<classes>
<class name="DockerStandaloneTest"/>
</classes>
</test>
<test name="EdgeTest">
<parameter name="browser" value="edge"/>
<classes>
<class name="DockerStandaloneTest"/>
</classes>
</test>
</suite>
So the Chrome container will run test on Chrome browser, Firefox container will run test on Firefox and Edge container will run test on Edge.
View test run visually on browser
New version of standalone container from selenium has provided noVNC to allow user to inspect what is running in browser. We do not need to install VNC client to do this anymore.
To see what is happening inside the container, head to:
Chrome container: http://localhost:7901/?autoconnect=1&resize=scale&password=secret
Firefox container: http://localhost:7902/?autoconnect=1&resize=scale&password=secret
Edge container: http://localhost:7903/?autoconnect=1&resize=scale&password=secret
or simply: http://localhost:7901 and provide password "secret" when it is asked.
When there are no test running
And when test running
Another approach for us to view this is to click on video icon next to session id under Sessions tab.
Set up Selenium Grid with Docker - Hub and Node mode
The Hub and Nodes will be created on different machines/VMs, they need to know each other's IPs to communicate properly. If more than one node will be running on the same Machine/VM, they must be configured to expose different ports.
And as I already mentioned, using different containers for hub and nodes, it is the same concept with setting up Hub and Nodes on different machines, which requires us to specify Event Bus, Publish Event port and Subscribe Event port.
Hub - Machine/VM 1
By default, port 4444 is registered for server whereas 4442 and 4443 are exposed for Event Bus ports
docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.7.2-20221219
Node Chrome - Machine/VM 2
Default port of Node is 5555, so we simply expose that
Event Bus Host need to be set up with IP of Hub machine
Node host is current IP of this Node machine
Replace ^ with ` if you are using Linux/macOS/PowerShell, below example is for Windows CMD
docker run -d -p 5555:5555 ^
--shm-size="2g" ^
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> ^
-e SE_EVENT_BUS_PUBLISH_PORT=4442 ^
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ^
-e SE_NODE_HOST=<ip-from-machine-2> ^
selenium/node-chrome:4.7.2-20221219
Node Firefox - Machine/VM 3
Same set up applied for Firefox node machine with few modifications about node IP and image
docker run -d -p 5555:5555 ^
--shm-size="2g" ^
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> ^
-e SE_EVENT_BUS_PUBLISH_PORT=4442 ^
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ^
-e SE_NODE_HOST=<ip-from-machine-3> ^
selenium/node-firefox:4.7.2-20221219
Node Edge - Machine/VM 4
Same set up applied for Edge node machine with few modifications about node IP and image
docker run -d -p 5555:5555 ^
--shm-size="2g" ^
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> ^
-e SE_EVENT_BUS_PUBLISH_PORT=4442 ^
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ^
-e SE_NODE_HOST=<ip-from-machine-4> ^
selenium/node-edge:4.7.2-20221219
Point test to exposed IP of hub
This just works seamlessly
driver = new RemoteWebDriver(new URL("http://<ip-from-machine-1>:4444"),capabilities);
Try to write your own test and see how it works đ.
Summary
The major downside of performing tests in a standalone container is low scalability. Hence, running Selenium in a standalone (or single) container is only suited for small projects. Whereas hub and node mode is definitely best fit for medium and a bit large demand (5 to < 100 nodes).
So it is all about setting and an example on how to run test with it. Hope it was able to bring an entirely fresh perspective to Selenium test automation for distributed testing to you.
Check out my repo: https://github.com/trongtuyen96/selenium-grid-docker-zalenium
for more details.
Next, Part 3, will be about setting up Grid with Docker compose. Stay tuned đ!!!