← Blog

"Selenium Series #15: Selenium Grid — Parallel Execution Across Multiple Machines"

Scale from 4 parallel tests to 40 using Selenium Grid. Set up Hub and Node architecture, run tests on remote machines, integrate with Docker Grid, and connect to cloud platforms.

– reading now
– views
– comments

Series Navigation

← Part 14: Cross-Browser Testing

→ Part 16: CI/CD Integration — Jenkins and Maven Surefire


Why Selenium Grid?

Running 4 parallel tests on one machine is limited by your CPU. Selenium Grid distributes tests across multiple machines:

Without Grid:
Machine 1: [Test1] [Test2] [Test3] [Test4]  ← limited by CPUs

With Grid:
Hub (coordinator)
├── Node 1 (Windows): [Test1] [Test5] [Test9]
├── Node 2 (Linux):   [Test2] [Test6] [Test10]
├── Node 3 (macOS):   [Test3] [Test7] [Test11]
└── Node 4 (Linux):   [Test4] [Test8] [Test12]

Selenium Grid 3 — Hub and Node

Start the Hub

# Download selenium-server-standalone-3.141.59.jar
java -jar selenium-server-standalone-3.141.59.jar -role hub -port 4444

Hub is now running at http://hub-machine:4444/grid/console

Start Nodes

# On each node machine:
java -jar selenium-server-standalone-3.141.59.jar \
  -role node \
  -hub http://hub-machine:4444/grid/register \
  -port 5555 \
  -maxSession 5 \
  -browser "browserName=chrome,maxInstances=5" \
  -browser "browserName=firefox,maxInstances=3"

Connect Tests to Grid

// Replace local driver creation with RemoteWebDriver
DesiredCapabilities caps = new DesiredCapabilities();
caps.setBrowserName("chrome");
caps.setPlatform(Platform.LINUX);

WebDriver driver = new RemoteWebDriver(
    new URL("http://hub-machine:4444/wd/hub"),
    caps
);

Selenium Grid 4 — Standalone and Distributed

Selenium 4 (released 2021) revamped Grid with a new architecture:

Standalone Mode (single machine)

# Download selenium-server-4.x.x.jar
java -jar selenium-server-4.1.0.jar standalone --port 4444

# Tests connect the same way
WebDriver driver = new RemoteWebDriver(
    new URL("http://localhost:4444"),
    new ChromeOptions()
);

Distributed Mode

# Start Event Bus
java -jar selenium-server.jar event-bus --port 4442 --publish-events tcp://*:4442 --subscribe-events tcp://*:4443

# Start Session Map
java -jar selenium-server.jar sessions --session-map redis://localhost:6379

# Start Router
java -jar selenium-server.jar router --hub http://localhost:4444 --sessions http://localhost:5556 --distributor http://localhost:5553

# Start Node
java -jar selenium-server.jar node --hub http://localhost:4444

Docker Selenium Grid

The simplest Grid setup uses Docker Compose:

# docker-compose.yml
version: "3"
services:

  selenium-hub:
    image: selenium/hub:4.1.0
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

  chrome-node:
    image: selenium/node-chrome:4.1.0
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=3
    volumes:
      - /dev/shm:/dev/shm

  firefox-node:
    image: selenium/node-firefox:4.1.0
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

  edge-node:
    image: selenium/node-edge:4.1.0
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
# Start the Grid
docker-compose up -d

# Scale nodes on demand
docker-compose up -d --scale chrome-node=5

# Check Grid status
open http://localhost:4444/grid/console

# Run tests
mvn test -Dgrid.url=http://localhost:4444

# Tear down
docker-compose down

Grid-Aware BaseTest

@BeforeMethod
@Parameters({"browser", "gridUrl"})
public void setUp(
    @Optional("chrome") String browser,
    @Optional("") String gridUrl
) throws MalformedURLException {

    WebDriver driver;

    if (!gridUrl.isEmpty()) {
        // Run on Grid
        ChromeOptions opts = new ChromeOptions();
        opts.addArguments("--no-sandbox", "--disable-dev-shm-usage");

        driver = new RemoteWebDriver(new URL(gridUrl), opts);
        System.out.println("Using Grid: " + gridUrl);
    } else {
        // Run locally
        driver = DriverFactory.createDriver(browser, false);
        System.out.println("Using local: " + browser);
    }

    driverThreadLocal.set(driver);
}
# Local
mvn test

# Grid
mvn test -DgridUrl=http://selenium-hub:4444

What's Next

In Part 16 we integrate our full test suite into Jenkins — configuring Maven builds, running tests on every commit, publishing HTML reports, and sending email notifications on failure.

Discussion

Loading...

Leave a Comment

All comments are reviewed before appearing. No links please.

0 / 1000